2008-12-15 15 views

Odpowiedz

238

Jeśli masz inny zmienna również odnoszące się do tego samego słownika, istnieje duża różnica:

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

To dlatego przypisanie d = {} tworzy nową, pustą słownika i przypisuje go do d zmienna. Pozostawia to d2 wskazujące na stary słownik z wciąż znajdującymi się w nim elementami. Jednak d.clear() usuwa ten sam słownik, z którym oba są oznaczone jako d i .

+5

Dzięki. To ma sens. Nadal muszę się przyzwyczaić do sposobu myślenia, który = tworzy odniesienia w pythonie ... – Marcin

+8

= kopiuje odniesienia do nazw. W pythonie nie ma zmiennych, tylko obiekty i nazwy. – tzot

+15

Chociaż twoje stwierdzenie "bez zmiennych" jest pedantycznie prawdziwe, nie jest tu zbyt pomocne. Dopóki dokumentacja w języku Python nadal mówi o "zmiennych", nadal używam terminu: http://docs.python.org/reference/datamodel.html –

26

d = {} utworzy nowe wystąpienie dla d, ale wszystkie inne odniesienia będą nadal wskazywać na starą zawartość. d.clear() zresetuje zawartość, ale wszystkie odniesienia do tej samej instancji będą nadal poprawne.

18

Oprócz różnic wymienionych w innych odpowiedziach występuje również różnica prędkości. d = {} jest ponad dwa razy szybciej:

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 
+7

To naprawdę nie jest ważny test prędkości dla wszystkich przypadków, ponieważ dyktat jest pusty. Wydaje mi się, że zrobienie dużego dicta (lub przynajmniej trochę treści) przyniosłoby znacznie mniejszą różnicę w wydajności ... plus podejrzewam, że śmieciarz mógłby dodać trochę własnego bólu do d = {} (?) – Rafe

+0

@Rafe: I Myślę, że chodzi o to, że jeśli wiemy, że żadna inna zmienna nie wskazuje na słownik d, to ustawienie 'd = {}' powinno być szybsze, ponieważ czyszczenie całości może być pozostawione na Garbage Collector na później. – ViFI

5

Jako ilustracja na rzeczy już wspomniane wcześniej:

>>> a = {1:2} 
>>> id(a) 
3073677212L 
>>> a.clear() 
>>> id(a) 
3073677212L 
>>> a = {} 
>>> id(a) 
3073675716L 
+0

To pokazuje, że '.clear' modyfikuje obiekt, ale' = {} 'tworzy nowy obiekt. – wizzwizz4

7

oprócz @odano „s odpowiedź wydaje się, używając d.clear() jest szybciej, jeśli chciałbyś wyczyścić dyktę wiele razy.

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) 

Wynikiem jest:

20.0367929935 
19.6444659233 
+3

Nie jestem pewien, czy różnica jest znacząca. W każdym razie na mojej maszynie wyniki są odwrotne! – Aristide

4

Jedno nie jest wymienione kwestie określania zakresu. Nie jest to świetny przykład, ale tutaj jest przypadek, gdy wpadłem na ten 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ązaniem jest zastąpienie c_kwargs = {} z c_kwargs.clear()

Jeśli ktoś uważa się bardziej praktyczny przykład, nie krępuj się, aby edytować ten post .

+0

'global c_kwargs' prawdopodobnie też by działało nie? Chociaż prawdopodobnie "globalne" nie jest najlepszą rzeczą, z której można korzystać bardzo często. – fantabolous

+3

@fantabolous za pomocą 'global' spowodowałby, że funkcja zachowywałaby się inaczej - wszystkie wywołania conf_decorator miałyby wówczas wspólną tę samą zmienną c_kwargs. Wierzę, że Python 3 dodał słowo kluczowe "nielokalny", aby rozwiązać ten problem, a to by działało. – Ponkadoodle

5

Mutowanie metodami zawsze Przydatne jeśli obiekt nie znajduje się w zakresie:

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

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

ponownego przydzielania słownika by utworzyć nowy przedmiot i nie modyfikować pierwotnego.

0

Ponadto, czasami instancja dict może być podklasą dyktowania (na przykład: defaultdict). W takim przypadku preferowane jest używanie clear, ponieważ nie musimy pamiętać dokładnego typu dyktanda, a także unikamy powtarzania kodu (połączenie linii czyszczącej z linią inicjalizacji).

x = defaultdict(list) 
x[1].append(2) 
... 
x.clear() # instead of the longer x = defaultdict(list)