Diferencia entre dict.clear () y asignar {} en Python


En python, ¿hay una diferencia entre llamar a clear() y asignar {} a un diccionario? En caso afirmativo, ¿qué es? Ejemplo:

d = {"stuff":"things"}
d.clear()   #this way
d = {}      #vs this way
Author: Michael Hoffman, 2008-12-16

8 answers

Si tienes otra variable que también se refiere al mismo diccionario, hay una gran diferencia:

>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}

Esto se debe a que asignar d = {} crea un nuevo diccionario vacío y lo asigna a la variable d. Esto deja d2 apuntando al viejo diccionario con elementos todavía en él. Sin embargo, d.clear() borra el mismo diccionario que d y d2 señalan.

 250
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-15 22:30:29

d = {} creará una nueva instancia para d pero todas las demás referencias seguirán apuntando al contenido antiguo. d.clear() restablecerá el contenido, pero todas las referencias a la misma instancia seguirán siendo correctas.

 26
Author: Michel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-25 10:23:43

Además De las diferencias mencionadas en otras respuestas, también hay una diferencia de velocidad. d = {} es más del doble de rápido:

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
 20
Author: odano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 11:31:10

Además de la respuesta de @odano, parece que usar d.clear() es más rápido si desea borrar el dictado muchas veces.

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)

El resultado es:

20.0367929935
19.6444659233
 7
Author: lastland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-25 08:41:33

Como ilustración de las cosas ya mencionadas:

>>> a = {1:2}
>>> id(a)
3073677212L
>>> a.clear()
>>> id(a)
3073677212L
>>> a = {}
>>> id(a)
3073675716L
 6
Author: maxp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-08 08:34:25

Los métodos mutantes siempre son útiles si el objeto original no está en el alcance:

def fun(d):
    d.clear()
    d["b"] = 2

d={"a": 2}
fun(d)
d          # {'b': 2}

Reasignar el diccionario crearía un nuevo objeto y no modificaría el original.

 5
Author: Karoly Horvath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-25 10:27:12

Una cosa que no se menciona son los problemas de alcance. No es un gran ejemplo, pero aquí está el caso donde me encontré con el problema:

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

La solución es sustituir c_kwargs = {} por c_kwargs.clear()

Si alguien piensa en un ejemplo más práctico, no dude en editar este post.

 4
Author: Ponkadoodle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-26 01:53:11

Además, a veces la instancia dict podría ser una subclase de dict (defaultdict por ejemplo). En ese caso, se prefiere usar clear, ya que no tenemos que recordar el tipo exacto del dict, y también evitar el código duplicado (acoplando la línea de compensación con la línea de inicialización).

x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)
 0
Author: Tzach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-03 11:47:11