2016-06-16 17 views
9

Robię rzeczy głównie w C++, gdzie metoda destruktora jest przeznaczona do zniszczenia pozyskanego zasobu. Ostatnio zacząłem od pythona (co jest naprawdę zabawne i fantastyczne) i przyjąłem, że ma GC jak java. Tak więc nie ma dużego nacisku na własność obiektu (konstrukcja i zniszczenie).Czy __del__ naprawdę jest destruktorem?

O ile wiem, metoda __init__() ma dla mnie więcej sensu w pythonie niż w przypadku ruby, ale metoda __del__(), czy naprawdę musimy wdrożyć tę wbudowaną funkcję w naszej klasie? Czy mojej klasie czegoś brakuje, jeśli tęsknię za __del__()? Jedynym scenariuszem, który mogłem zobaczyć, jest przydatność, jeśli chcę coś logować podczas niszczenia obiektu. Czy jest coś innego niż to?

+4

Nie. Prawie nigdy nie należy implementować '__del__'. –

+0

http://stackoverflow.com/a/2433847/2681632 –

+3

Ty * prawie nigdy * chcesz zaimplementować '__del__'. Klasy, które zapewniają niestandardowe '__del__', muszą być traktowane w specjalny sposób przez GC podczas pracy z cyklami (ponieważ' __del__' musi być wywołany dokładnie raz), a w niektórych przypadkach GC nie będzie w stanie ich zebrać [chociaż od python3.4 + zostało to znacznie poprawione]. Jest bardzo mało przypadków, w których dobrze jest go wdrożyć. – Bakuriu

Odpowiedz

10

Z Python 3 docs:

object.__del__(self)

Wywoływana, gdy instancja ma zostać zniszczona. Nazywa się to także destruktorem. Jeśli klasa bazowa ma metodę __del__(), metoda klasy pochodnej, __del__(), musi ją jawnie wywoływać, aby zapewnić poprawne usunięcie części instancji klasy podstawowej.

Więc w rzeczywistości jest destruktor (ale można jawnie nazwać siebie jako metody klasy).

Jednak z other answers ale także z Wikipedia:

w języku z automatycznym mechanizmem zbierania śmieci, to trudno byłoby deterministycznie zapewnić wywołanie destruktora, a więc te języki są powszechnie uważane nieodpowiedni dla RAII [zasobu nabycia jest inicjalizacji]

należy więc prawie nigdy nie być wdrożenie __del__, ale daje możliwość, aby to zrobić w kilku (rzadko?) użyć przypadki

+3

Jednym ze sposobów jest zapewnienie, że krytyczny zasób zostanie oczyszczony, zanim obiekt zostanie zebrany. To znaczy. w '__del__' sprawdź, czy zasób jest zamknięty normalnie, a jeśli nie, zrób to i wystaw ostrzeżenie. – doublep

1

Czy del naprawdę jest destruktorem?

Nie, __del__ metoda nie jest destruktor, jest po prostu normalny sposób można zadzwonić, gdy chcesz wykonać dowolną operację, ale zawsze jest wywoływana przed garbage collector niszczy obiekt. Pomyśl o tym jak o czystej lub ostatniej woli.

+0

Czy wywołanie __del__ będzie miało miejsce, gdy ma się wydarzyć lub jak to, co mamy jako finalize() w java, Słyszałem, że wywołanie finalize() jest nieprzewidywalne –

+0

@Explorer_N, to zawsze będzie wywoływane przez interpreter python kiedy obiekt ma zostać usunięty. – Netwave

5

Jak już zaznaczono w innych odpowiedziach, prawdopodobnie nie należy implementować __del__ w języku Python. Jeśli znajdziesz się w sytuacji, myśląc, że naprawdę potrzebujesz destruktora (na przykład, jeśli twoja klasa zawija zasób, który musi być jawnie zamknięty), to Pythonicznym sposobem na przejście jest użycie context managers.

+0

Łącze do menedżera kontekstu było dobre, czy każdy obiekt (w tym typ użytkownika) implementuje menedżera kontekstów? –

+1

@Explorer_N Nie, musisz zrobić to sam. I oni też nie mają tych samych sematycznie. Ale łatwo to zrobić. – glglgl

+1

@Explorer_N: Podczas gdy zazwyczaj musisz zaimplementować tę funkcję samodzielnie dla klas niestandardowych, często bardzo łatwo jest skorzystać z pomocy modułów ['contextlib'] (https://docs.python.org/3/library/contextlib.html). –

Powiązane problemy