Trong python, có sự khác biệt giữa gọi clear()
và gán {}
cho một từ điển? Nếu có, nó là cái gì? Thí dụ:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Trong python, có sự khác biệt giữa gọi clear()
và gán {}
cho một từ điển? Nếu có, nó là cái gì? Thí dụ:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Câu trả lời:
Nếu bạn có một biến khác cũng đề cập đến cùng một từ điển, có một sự khác biệt lớn:
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}
Điều này là do việc gán d = {}
tạo ra một từ điển mới, trống và gán nó cho d
biến. Lá này d2
chỉ vào từ điển cũ với các mục vẫn còn trong đó. Tuy nhiên, d.clear()
xóa cùng một từ điển d
và d2
cả hai điểm.
Ngoài sự khác biệt được đề cập trong các câu trả lời khác, còn có sự khác biệt về tốc độ. d = {} nhanh hơn gấp đôi:
python -m timeit -s "d = {}" "for i in xrange(500000): d.clear()"
10 loops, best of 3: 127 msec per loop
python -m timeit -s "d = {}" "for i in xrange(500000): d = {}"
10 loops, best of 3: 53.6 msec per loop
d = {}
sẽ nhanh hơn vì việc dọn dẹp toàn bộ có thể được để lại cho Garbage Collector sau này.
Ngoài câu trả lời của @odano, có vẻ như việc sử dụng d.clear()
sẽ nhanh hơn nếu bạn muốn xóa chính tả nhiều lần.
import timeit
p1 = '''
d = {}
for i in xrange(1000):
d[i] = i * i
for j in xrange(100):
d = {}
for i in xrange(1000):
d[i] = i * i
'''
p2 = '''
d = {}
for i in xrange(1000):
d[i] = i * i
for j in xrange(100):
d.clear()
for i in xrange(1000):
d[i] = i * i
'''
print timeit.timeit(p1, number=1000)
print timeit.timeit(p2, number=1000)
Kết quả là:
20.0367929935
19.6444659233
Các phương thức gây đột biến luôn hữu ích nếu đối tượng ban đầu không nằm trong phạm vi:
def fun(d):
d.clear()
d["b"] = 2
d={"a": 2}
fun(d)
d # {'b': 2}
Việc gán lại từ điển sẽ tạo ra một đối tượng mới và sẽ không sửa đổi đối tượng ban đầu.
Một điều không được đề cập là vấn đề phạm vi. Không phải là một ví dụ tuyệt vời, nhưng đây là trường hợp tôi gặp phải vấn đề:
def conf_decorator(dec):
"""Enables behavior like this:
@threaded
def f(): ...
or
@threaded(thread=KThread)
def f(): ...
(assuming threaded is wrapped with this function.)
Sends any accumulated kwargs to threaded.
"""
c_kwargs = {}
@wraps(dec)
def wrapped(f=None, **kwargs):
if f:
r = dec(f, **c_kwargs)
c_kwargs = {}
return r
else:
c_kwargs.update(kwargs) #<- UnboundLocalError: local variable 'c_kwargs' referenced before assignment
return wrapped
return wrapped
Giải pháp là thay thế c_kwargs = {}
bằngc_kwargs.clear()
Nếu ai đó nghĩ ra một ví dụ thực tế hơn, vui lòng chỉnh sửa bài đăng này.
global c_kwargs
có lẽ cũng sẽ làm việc không? Mặc dù có lẽ global
không phải là thứ tốt nhất để sử dụng nhiều.
global
sẽ làm cho hàm hoạt động khác đi - tất cả các lệnh gọi tới conf_decorator sau đó sẽ chia sẻ cùng một biến c_kwargs. Tôi tin rằng Python 3 đã thêm nonlocal
từ khóa để giải quyết vấn đề này và nó sẽ hoạt động.
Ngoài ra, đôi khi thể hiện dict có thể là một lớp con của dict ( defaultdict
ví dụ). Trong trường hợp đó, việc sử dụng clear
được ưu tiên hơn, vì chúng ta không phải nhớ chính xác loại chính tả và cũng tránh mã trùng lặp (ghép dòng xóa với dòng khởi tạo).
x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)