In python, is there a difference between calling clear() and assigning {} to a dictionary? If yes, what is it?
Example:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
If you have another variable also referring to the same dictionary, there is a big difference:
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}
This is because assigning d = {} creates a new, empty dictionary and assigns it to the d variable. This leaves d2 pointing at the old dictionary with items still in it. However, d.clear() clears the same dictionary that d and d2 both point at.
Method 2
d = {} will create a new instance for d but all other references will still point to the old contents.
d.clear() will reset the contents, but all references to the same instance will still be correct.
Method 3
In addition to the differences mentioned in other answers, there also is a speed difference. d = {} is over twice as fast:
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
Method 4
As an illustration for the things already mentioned before:
>>> a = {1:2}
>>> id(a)
3073677212L
>>> a.clear()
>>> id(a)
3073677212L
>>> a = {}
>>> id(a)
3073675716L
Method 5
In addition to @odano ‘s answer, it seems using d.clear() is faster if you would like to clear the dict for many times.
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)
The result is:
20.0367929935 19.6444659233
Method 6
Mutating methods are always useful if the original object is not in scope:
def fun(d):
d.clear()
d["b"] = 2
d={"a": 2}
fun(d)
d # {'b': 2}
Re-assigning the dictionary would create a new object and wouldn’t modify the original one.
Method 7
One thing not mentioned is scoping issues. Not a great example, but here’s the case where I ran into the problem:
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
The solution is to replace c_kwargs = {} with c_kwargs.clear()
If someone thinks up a more practical example, feel free to edit this post.
Method 8
In addition, sometimes the dict instance might be a subclass of dict (defaultdict for example). In that case, using clear is preferred, as we don’t have to remember the exact type of the dict, and also avoid duplicate code (coupling the clearing line with the initialization line).
x = defaultdict(list) x[1].append(2) ... x.clear() # instead of the longer x = defaultdict(list)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0