En python, y a-t-il une différence entre appeler clear()et assigner {}à un dictionnaire? Si oui, qu'est ce que c'est? Exemple:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
En python, y a-t-il une différence entre appeler clear()et assigner {}à un dictionnaire? Si oui, qu'est ce que c'est? Exemple:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Réponses:
Si vous avez une autre variable faisant également référence au même dictionnaire, il y a une grande différence:
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}
En effet, l'affectation d = {}crée un nouveau dictionnaire vide et l'affecte à la dvariable. Cela laisse d2pointer vers l'ancien dictionnaire avec des éléments toujours dedans. Cependant, d.clear()efface le même dictionnaire vers lequel det les d2deux pointent.
En plus des différences mentionnées dans d'autres réponses, il y a aussi une différence de vitesse. d = {} est deux fois plus rapide:
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 = {}devrait être plus rapide car le nettoyage de l'ensemble peut être laissé à Garbage Collector pour plus tard.
En plus de la réponse de @odano, il semble que l'utilisation d.clear()soit plus rapide si vous souhaitez effacer le dict plusieurs fois.
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)
Le résultat est:
20.0367929935
19.6444659233
Les méthodes de mutation sont toujours utiles si l'objet d'origine n'est pas dans la portée:
def fun(d):
d.clear()
d["b"] = 2
d={"a": 2}
fun(d)
d # {'b': 2}
Réaffecter le dictionnaire créerait un nouvel objet et ne modifierait pas l'original.
Une chose qui n'a pas été mentionnée concerne les problèmes de portée. Ce n'est pas un bon exemple, mais voici le cas où j'ai rencontré le problème:
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 solution est de remplacer c_kwargs = {}parc_kwargs.clear()
Si quelqu'un imagine un exemple plus pratique, n'hésitez pas à modifier ce message.
global c_kwargsfonctionnerait probablement aussi non? Bien que ce globalne soit probablement pas la meilleure chose à utiliser beaucoup.
globalferait la fonction se comporter différemment - tous les appels à conf_decorator partageraient alors la même variable c_kwargs. Je pense que Python 3 a ajouté le nonlocalmot - clé pour résoudre ce problème, et cela fonctionnerait.
De plus, parfois l'instance de dict peut être une sous-classe de dict ( defaultdictpar exemple). Dans ce cas, l'utilisation clearest préférable, car nous n'avons pas à nous souvenir du type exact du dict, et évitez également le code en double (couplage de la ligne de compensation avec la ligne d'initialisation).
x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)