Czytam kod. Istnieje klasa, w której zdefiniowano metodę __del__
. Doszedłem do wniosku, że ta metoda służy do zniszczenia instancji klasy. Jednak nie mogę znaleźć miejsca, w którym ta metoda jest używana. Głównym powodem tego jest to, że nie wiem, jak ta metoda jest używana, prawdopodobnie nie w ten sposób: obj1.del()
. Tak więc, moje pytania brzmią jak wywołać metodę __del__
? Dziękuję za pomoc.Co to jest metoda __del__, jak ją nazwać?
Odpowiedz
__del__
to destruktor. Jest wywoływana, gdy obiekt jest śmieci zebrane, co dzieje się po usunięciu wszystkich odniesień do obiektu.
W prostym przypadku to może być tuż po mówisz del x
lub, jeśli x
jest zmienna lokalna, po zakończeniu funkcji. W szczególności, jeśli nie ma odniesień kołowych, CPython (standardowa implementacja Pythona) będzie natychmiast zbierać śmieci.
Jest to jednak szczegóły implementacji z CPython. Jedynym wymagane własnością Python zbierania śmieci jest to, że dzieje się po wszystkie odniesienia zostały usunięte, więc może to nie jest konieczne stało zaraz po i nie może się zdarzyć w ogóle.
Co więcej, zmienne mogą pozostawać przez długi czas przez wiele różnych powodów , np., np. Wyjątek propagujący lub introspekcja modułu może przechowywać zmienną liczbę odwołań większą niż 0. Ponadto zmienna może być częścią cyklu odwołań - CPython z włączonym wyrzucaniem śmieci łamie większość, ale nie wszystkie, takie cykle, a nawet wtedy tylko okresowo .
Ponieważ nie ma gwarancji, to wykonane, trzeba nigdy umieścić kod, który trzeba uruchomić w __del__()
- zamiast, kod ten należy do finally
klauzuli bloku try
lub kierownika kontekstowego w with
rachunku . Istnieją jednak ważne przypadki użycia dla __del__
: np. jeżeli obiekt X
odwołuje się do Y
, a także zachowuje kopię odwołania o numerze Y
w globalnym cache
(cache['X -> Y'] = Y
), to byłoby uprzejme, aby X.__del__
również usunąć wpis pamięci podręcznej.
Jeśli znasz że destruktor zapewnia (naruszenie powyższej wytycznej) wymagany porządki, to może chcieć rozmowy bezpośrednio, ponieważ nie ma nic szczególnego o nim jako o metodzie: x.__del__()
. Oczywiście powinieneś to zrobić tylko wtedy, gdy wiesz, że nie ma nic przeciwko temu, aby zostać wezwanym dwukrotnie. Lub, w ostateczności, można ponownie zdefiniować tę metodę przy użyciu
type(x).__del__ = my_safe_cleanup_method
The __del__
metodę (zauważ pisowni!) Jest wywoływana, gdy obiekt zostanie ostatecznie zniszczony. Technicznie rzecz biorąc (w cPython), kiedy nie ma więcej odniesień do twojego obiektu, tj. Kiedy wykracza poza zakres.
Jeśli chcesz usunąć przedmiot, a tym samym wywołać użycie __del__
metody
del obj1
który będzie usunąć obiekt (o ile nie było żadnych innych odniesień do niego).
Proponuję napisać mały klasy jak ten
class T:
def __del__(self):
print "deleted"
i badać w interpretera Pythona, np
>>> a = T()
>>> del a
deleted
>>> a = T()
>>> b = a
>>> del b
>>> del a
deleted
>>> def fn():
... a = T()
... print "exiting fn"
...
>>> fn()
exiting fn
deleted
>>>
pamiętać, że Jython i IronPython mają różne zasady, aby dokładnie kiedy obiekt jest usunięto i wywołano __del__
. Nie uważa się za dobrą praktykę stosowania __del__
, ale z tego powodu oraz faktu, że obiekt i jego otoczenie mogą znajdować się w nieznanym stanie, gdy zostanie wywołany. Nie jest absolutnie zagwarantowane, że zostanie wywołana __del__
- interpreter może wyjść na różne sposoby, nie usuwając wszystkich obiektów.
w porównaniu z http://stackoverflow.com/a/2452895/611007 i http://stackoverflow.com/a/1481512/611007,' use del obj1' wygląda na zły pomysł polegać na. – n611x007
Metoda __del__
, zostanie wywołana, gdy obiekt zostanie zebrany śmieci. Zwróć uwagę, że niekoniecznie gwarantuje się, że zostanie wywołana. Poniższy kod sam w sobie nie musi to zrobić:
del obj
Wynika to z faktu, że del
tylko zmniejsza liczbę odwołań o jeden. Jeśli coś innego ma odniesienie do obiektu, __del__
nie zostanie wywołane.
Jednak istnieje kilka zastrzeżeń dotyczących korzystania z __del__
. Zazwyczaj po prostu nie są zbyt użyteczne. Brzmi dla mnie bardziej, jakbyś chciał użyć metody zamkniętej lub może with statement.
Zobacz python documentation on __del__
methods.
Jedna rzecz do zapamiętania: __del__
metody mogą hamować zbieranie śmieci, jeśli są nadużywane. W szczególności odwołanie cykliczne zawierające więcej niż jeden obiekt przy użyciu metody __del__
nie spowoduje pobrania śmieci. Dzieje się tak, ponieważ śmieciarz nie wie, który z nich zadzwonić pierwszy. Więcej informacji znajduje się w dokumentacji na stronie gc module.
Napisałem odpowiedź na kolejne pytanie, chociaż jest to bardziej dokładne pytanie.
Oto nieco uparty odpowiedź. Nie należy używać __del__
. To nie jest C++ ani język zbudowany dla destruktorów. Metoda __del__
powinna zniknąć w Pythonie 3.x, ale jestem pewna, że ktoś znajdzie przypadek użycia, który ma sens. Jeśli trzeba użyć __del__
, należy pamiętać o podstawowych ograniczeń za http://docs.python.org/reference/datamodel.html:
__del__
jest wywoływana, gdy garbage collector dzieje się zbieranie przedmiotów, a nie kiedy straci ostatni odniesienie do obiektu, a nie wtedy, gdy wykonajdel object
.__del__
jest odpowiedzialna za wywoływanie dowolnego__del__
w superklasie, choć nie jest jasne, czy jest to w porządku rozstrzygania metod (MRO), czy po prostu wywoływania każdej nadklasy.- Posiadanie
__del__
oznacza, że śmieciarz rezygnuje z wykrywania i czyszczenia wszelkich połączeń cyklicznych, takich jak utrata ostatniego odnośnika do połączonej listy. Możesz uzyskać listę obiektów ignorowanych z gc.garbage. Możesz czasami używać słabych odniesień, aby całkowicie uniknąć cyklu. Od tego czasu debatuje się: zobacz http://mail.python.org/pipermail/python-ideas/2009-October/006194.html. - Funkcja
__del__
może oszukiwać, zapisywać odniesienie do obiektu i zatrzymywać odśmiecanie. - Wyjątki jawnie podniesione w
__del__
są ignorowane. __del__
uzupełnia__new__
znacznie więcej niż__init__
. To staje się mylące. Zobacz http://www.algorithm.co.il/blogs/programming/python-gotchas-1-del-is-not-the-opposite-of-init/, aby uzyskać wyjaśnienie i sugestie.__del__
nie jest "dobrze kochanym" dzieckiem w Pythonie. Zauważysz, że dokumentacja sys.exit() nie określa, czy śmieci są zbierane przed wyjściem, i istnieje wiele dziwnych problemów. Wywołanie globali o numerze__del__
powoduje nieparzyste problemy z zamawianiem, np. http://bugs.python.org/issue5099. Czy należy zadzwonić pod numer__del__
, nawet jeśli__init__
ulegnie awarii? Zobacz http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423 dla długiego wątku.
Ale z drugiej strony:
__del__
oznacza, że nie zapomni zadzwonić bliskie oświadczenie. Zobacz http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/ dla punktu widzenia pro__del__
. Zazwyczaj chodzi o uwolnienie ctypów lub innych specjalnych zasobów.
I mój ponowny powód, dla którego nie lubię funkcji __del__
.
- Za każdym razem, gdy ktoś przywołuje
__del__
, przechodzi na trzydzieści wiadomości o pomieszaniu. - To łamie te elementy w Zen Pythona:
- Proste jest lepsze niż skomplikowane.
- Przypadki specjalne nie są wystarczająco szczególne, aby złamać zasady.
- Błędy nigdy nie powinny przechodzić w ciszy.
- W obliczu niejednoznaczności odrzuć pokusę odgadnięcia.
- Powinien istnieć jeden - a najlepiej tylko jeden - czysty sposób na zrobienie tego.
- Jeśli implementacja jest trudna do wyjaśnienia, jest to zły pomysł.
więc znaleźć powód, aby nie używać __del__
.
Nawet jeśli pytanie nie jest dokładnie: dlaczego nie powinniśmy używać '__del__', ale jak nazwać' __del__', twoja odpowiedź jest interesująca. – nbro
Dzięki. Czasami najlepszym pomysłem jest odejście od okropnych pomysłów. –
W innych wiadomościach, zapomniałem wspomnieć, że PyPy (szybszy interpreter dla dłużej działających aplikacji) złamie __del__. –
- 1. Co to jest metoda inline?
- 2. Co to jest metoda getApplicationContext()?
- 3. Co to jest metoda generatywna?
- 4. Czy __del__ naprawdę jest destruktorem?
- 5. Co to jest "perspektywa" Eclipse i jak mam ją wykonać?
- 6. Co to jest "pułapka przerwania" i jak mogę ją debugować?
- 7. co to jest zmienna devise_mapping i jak ją uwzględnić?
- 8. Co to jest ślad aplikacji i jak ją obliczyć?
- 9. Co to jest metoda wygodna w Javie?
- 10. Co to jest metoda statyczna i zmienne?
- 11. Co to jest metoda ładowania początkowego?
- 12. Co to jest metoda skrótowa w MeteorJS?
- 13. Co to jest metoda Git do publikowania kolejki poprawek?
- 14. Co to jest $ {project.licensePath}?
- 15. Jak powinienem nazwać metodę, która to robi ...?
- 16. Co to jest []
- 17. Co to jest "Przenośny C++"?
- 18. to powrót funkcji konieczne nazwać zamknięcie
- 19. Co to jest Serializable? Co to znaczy?
- 20. Co to jest "menu kontekstowe" i metoda registerForContextMenu()
- 21. Co to jest metoda z ikoną gwiazdki w czasie zaćmienia?
- 22. Co to jest proc i metoda w reakcji na javascript?
- 23. Python AttributeError na __del__
- 24. To, co się nazywa po metoda onConfigurationchanged()
- 25. Co to jest "usuń to"?
- 26. Co to jest ewolucja różnicowa i jak się ją porównuje do algorytmu genetycznego?
- 27. Co to jest znak 0x1f?
- 28. Co to jest atrybut antiJARLocking?
- 29. co to jest alloc.h?
- 30. Co to jest StackOverflowError?
Mówisz, że funkcja usuwania obiektu CPythona natychmiast po zredukowaniu liczby odwołań do zera jest "szczegółem implementacji". Nie jestem przekonany. Czy możesz podać kopię zapasową tego roszczenia? (Chodzi mi o to, że pogrubiona czcionka * jest * całkiem przekonująca sama, ale linki są bliskie sekundy ...:-) –
** Szczegóły implementacji CPython: ** CPython obecnie używa schematu zliczającego odniesienia z (opcjonalnie) opóźnionym wykrywaniem cyklicznie powiązanych śmieci, ... Inne implementacje działają inaczej i CPython może się zmienić. (http://docs.python.org/2/reference/datamodel.html) –
Co z '__exit__' w tym kontekście? Czy jest uruchamiany po lub przed '__del__' lub razem? – lony