En python, ¿hay alguna diferencia entre llamar clear()y asignar {}a un diccionario? ¿Y si si, que? Ejemplo:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
En python, ¿hay alguna diferencia entre llamar clear()y asignar {}a un diccionario? ¿Y si si, que? Ejemplo:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Respuestas:
Si tiene 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 la asignación d = {}crea un nuevo diccionario vacío y lo asigna a la dvariable. Esto deja d2apuntando al antiguo diccionario con elementos todavía en él. Sin embargo, d.clear()borra el mismo diccionario que dy d2ambos apuntan a.
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
d = {}debería ser más rápida ya que la limpieza completa puede dejarse en el recolector de basura para más adelante.
Además de la respuesta de @odano, parece que el uso d.clear()es más rápido si desea borrar el dict 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
Los métodos de mutación siempre son útiles si el objeto original no está dentro del 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.
Una cosa que no se menciona son los problemas de alcance. No es un gran ejemplo, pero aquí está el caso en el que 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 reemplazar c_kwargs = {}conc_kwargs.clear()
Si alguien piensa en un ejemplo más práctico, siéntase libre de editar esta publicación.
global c_kwargsprobablemente también funcionaría no? Aunque probablemente globalno sea lo mejor para usar mucho.
globalharía que la función se comportara de manera diferente: todas las llamadas a conf_decorator compartirían la misma variable c_kwargs. Creo que Python 3 agregó la nonlocalpalabra clave para abordar este problema, y eso funcionaría.
Además, a veces la instancia dict puede ser una subclase de dict ( defaultdictpor ejemplo). En ese caso, clearse prefiere usar , ya que no tenemos que recordar el tipo exacto del dict, y también evitar el código duplicado (acoplar 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)