2012-03-28 16 views
32

Próbowałem zrozumieć, jak słabo działa lista słowników referencyjnych/słownika Pythona i czytałem dla niej także dokumentację, jednak nie mogę zrozumieć, jak one działają i do czego mogą być używane. Czy ktokolwiek mógłby mi dać podstawowy przykład tego, co robią/wyjaśnienia, jak działają? Byłoby to bardzo docenione.Słabe referencje w pytonie

(EDIT) Korzystanie kod Thomasa, kiedy zastąpił OBJ dla [1,2,3] rzuca:

Traceback (most recent call last): 
File "C:/Users/nonya/Desktop/test.py", line 9, in <module> 
r = weakref.ref(obj) 
TypeError: cannot create weak reference to 'list' object 

Odpowiedz

41

Teoria

Ilość referencyjna zwykle działa w następujący sposób: za każdym razem utworzyć odniesienie do obiektu, to zwiększa się o jeden, a kiedy usunąć odniesienie, to zmniejsza się o jeden.

Słabe odniesienia umożliwiają tworzenie odniesień do obiektu, który nie zwiększy liczby odwołań.

Licznik odwołań używany jest przez Garbage Collector Pythona, gdy działa: dowolny obiekt, którego licznik odwołania wynosi 0, będzie zbierał śmieci.

Używasz słabych odniesień dla drogich obiektów lub w celu uniknięcia odniesień do kół (chociaż śmieciarz zwykle robi to samodzielnie).

Wykorzystanie

Oto przykład pracy wykazując ich wykorzystania:

import weakref 
import gc 

class MyObject(object): 
    def my_method(self): 
     print 'my_method was called!' 

obj = MyObject() 
r = weakref.ref(obj) 

gc.collect() 
assert r() is obj #r() allows you to access the object referenced: it's there. 

obj = 1 #Let's change what obj references to 
gc.collect() 
assert r() is None #There is no object left: it was gc'ed. 
+0

Jak to działa na liście/słowniku, był to świetny przykład na zajęciach/funkcjach. :) –

+0

Proszę spojrzeć na moją edycję. podczas podstawiania listy lub słownika wyrzuca ten błąd. –

+0

Moja zła, całkowicie przeoczyłem to, nie możesz w rzeczywistości stworzyć słabego obiektu do "listy" lub innego typu kompozytowego - jaki jest twój dokładny cel, do którego go potrzebujesz? –

9

Chodzi o to, że pozwalają one odniesienia mają być zatrzymywane do obiektów bez zapobiegając ich od śmieci zebrane.

Dwa główne powody, dla których warto tego dokonać, to miejsce, w którym wykonuje się okresowe zarządzanie zasobami, np. zamykanie plików, ale ponieważ czas między tymi podaniami może być długi, śmieciarz może zrobić to za ciebie; lub gdzie tworzysz obiekt, a znalezienie go w programie może być względnie kosztowne, ale nadal chcesz zajmować się instancjami, które faktycznie istnieją.

Drugi przypadek jest prawdopodobnie bardziej powszechny - jest odpowiedni podczas przenoszenia np. listę obiektów do powiadomienia, a nie chcesz, aby system powiadomień zapobiegał wyrzucaniu śmieci.

+0

Być może 3 powody? trzecie zerwanie cyklicznych odniesień. – dashesy

+1

@dashy ma to prawo. Najczęstszym (na przykład jedynym bezpiecznym) przypadkiem użycia słabych odniesień jest jawne przerwanie cykli odniesienia. Pomimo tego, że odśmiecający Python może i tak i tak złamie takie cykle, to jest znacznie mniej czasu i czasu, aby zapobiec tworzeniu się takich cykli. Wszystkie inne zastosowania słabych odniesień są w najlepszym razie kruche i powinny być bezwzględnie traktowane z odrobiną lęku i szacunku. –

12

prostu chcę podkreślić, że weakref.ref nie działa dla listy wbudowanym ponieważ nie ma __weakref__ w __slots__ z lista. Na przykład poniższy kod definiuje kontener listy obsługujący weakref.

import weakref 

class weaklist(list): 
    __slots__ = '__weakref__', 

l = weaklist() 
r = weakref.ref(l)