In Python, c'è una differenza tra chiamare clear()e assegnare {}a un dizionario? Se si, che cos'è? Esempio:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
In Python, c'è una differenza tra chiamare clear()e assegnare {}a un dizionario? Se si, che cos'è? Esempio:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Risposte:
Se hai un'altra variabile che fa riferimento anche allo stesso dizionario, c'è una grande differenza:
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}
Questo perché l'assegnazione d = {}crea un nuovo dizionario vuoto e lo assegna alla dvariabile. Questo lascia d2puntare al vecchio dizionario con gli elementi ancora presenti. Tuttavia, d.clear()cancella lo stesso dizionario che de d2sia punto.
Oltre alle differenze menzionate in altre risposte, esiste anche una differenza di velocità. d = {} è due volte più veloce:
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 = {}dovrebbe essere più veloce poiché la pulizia completa può essere lasciata a Garbage Collector per dopo.
A titolo di esempio per le cose già menzionate prima:
>>> a = {1:2}
>>> id(a)
3073677212L
>>> a.clear()
>>> id(a)
3073677212L
>>> a = {}
>>> id(a)
3073675716L
.clearmodifica l'oggetto ma `= {}` crea un nuovo oggetto.
Oltre alla risposta di @odano, sembra che l'uso d.clear()sia più veloce se desideri cancellare il dict per molte volte.
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)
Il risultato è:
20.0367929935
19.6444659233
I metodi di mutazione sono sempre utili se l'oggetto originale non rientra nell'ambito:
def fun(d):
d.clear()
d["b"] = 2
d={"a": 2}
fun(d)
d # {'b': 2}
La riassegnazione del dizionario creerebbe un nuovo oggetto e non modificherebbe quello originale.
Una cosa non menzionata è problemi di scoping. Non è un ottimo esempio, ma ecco il caso in cui mi sono imbattuto nel 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 soluzione è sostituirla c_kwargs = {}conc_kwargs.clear()
Se qualcuno pensa a un esempio più pratico, non esitare a modificare questo post.
global c_kwargsprobabilmente funzionerebbe anche no? Anche se probabilmente globalnon è la cosa migliore da usare molto.
globalfarebbe in modo che la funzione si comporti diversamente: tutte le chiamate a conf_decorator condivideranno quindi la stessa variabile c_kwargs. Credo che Python 3 abbia aggiunto la nonlocalparola chiave per risolvere questo problema e che funzionerebbe.
Inoltre, a volte l'istanza di dict potrebbe essere una sottoclasse di dict ( defaultdictad esempio). In tal caso, clearè preferibile utilizzare , poiché non dobbiamo ricordare il tipo esatto di dict ed evitare anche il codice duplicato (accoppiando la linea di cancellazione con la linea di inizializzazione).
x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)