[python] Difference between dict.clear() and assigning {} in Python

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

This question is related to python dictionary

The answer is


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

As an illustration for the things already mentioned before:

>>> a = {1:2}
>>> id(a)
3073677212L
>>> a.clear()
>>> id(a)
3073677212L
>>> a = {}
>>> id(a)
3073675716L

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

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.


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.


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

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

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.


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)

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

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.


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.


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

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.


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)