Czy w Pythonie istnieje różnica między wywołaniem clear()
a przypisaniem {}
do słownika? Jeśli tak, co to jest? Przykład:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Czy w Pythonie istnieje różnica między wywołaniem clear()
a przypisaniem {}
do słownika? Jeśli tak, co to jest? Przykład:
d = {"stuff":"things"}
d.clear() #this way
d = {} #vs this way
Odpowiedzi:
Jeśli masz inną zmienną również odnoszącą się do tego samego słownika, jest duża różnica:
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d = {}
>>> d2
{'stuff': 'things'}
>>> d = {"stuff": "things"}
>>> d2 = d
>>> d.clear()
>>> d2
{}
Dzieje się tak, ponieważ przypisywanie d = {}
tworzy nowy, pusty słownik i przypisuje go do d
zmiennej. To pozostawia d2
wskazanie na stary słownik, w którym wciąż znajdują się pozycje. Jednak d.clear()
czyści ten sam słownik, który d
i d2
oba wskazują.
Oprócz różnic wymienionych w innych odpowiedziach istnieje również różnica prędkości. d = {} jest ponad dwukrotnie szybsze:
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 = {}
powinno być szybsze, ponieważ czyszczenie całości można pozostawić w Garbage Collector na później.
Oprócz odpowiedzi @odano wydaje się, że użycie d.clear()
jest szybsze, jeśli chcesz wielokrotnie wyczyścić dyktando.
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)
Wynik to:
20.0367929935
19.6444659233
Metody mutujące są zawsze przydatne, jeśli oryginalny obiekt nie znajduje się w zakresie:
def fun(d):
d.clear()
d["b"] = 2
d={"a": 2}
fun(d)
d # {'b': 2}
Ponowne przypisanie słownika spowodowałoby utworzenie nowego obiektu i nie zmodyfikowałoby oryginalnego.
Jedna rzecz, o której nie wspomniano, to kwestie dotyczące zakresu. Niezbyt dobry przykład, ale oto przypadek, w którym napotkałem 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
Rozwiązanie to zastępuje c_kwargs = {}
sięc_kwargs.clear()
Jeśli ktoś wymyśli bardziej praktyczny przykład, nie krępuj się edytować tego posta.
global c_kwargs
prawdopodobnie też by działało, nie? Chociaż prawdopodobnie global
nie jest najlepszą rzeczą, gdy używa się ich dużo.
global
spowodowałoby, że funkcja zachowywałaby się inaczej - wszystkie wywołania conf_decorator współdzieliłyby wówczas tę samą zmienną c_kwargs. Uważam, że Python 3 dodał nonlocal
słowo kluczowe, aby rozwiązać ten problem, i to zadziała.
Ponadto czasami instancja dict może być podklasą dict ( defaultdict
na przykład). W takim przypadku clear
preferowane jest użycie , ponieważ nie musimy pamiętać dokładnego typu dyktu, a także unikać duplikowania kodu (łączenia linii rozliczeniowej z linią inicjalizacyjną).
x = defaultdict(list)
x[1].append(2)
...
x.clear() # instead of the longer x = defaultdict(list)