__del__
является финализатором . Он вызывается, когда объект собирается сборщиком мусора, что происходит в какой-то момент после удаления всех ссылок на объект.
В простом случае это может быть сразу после того, как вы скажете, del x
или, если x
это локальная переменная, после завершения функции. В частности, если нет циклических ссылок, CPython (стандартная реализация Python) немедленно выполняет сборку мусора.
Однако это деталь реализации CPython. Единственное обязательное свойство сборки мусора Python - это то, что это происходит после удаления всех ссылок, поэтому это может не происходить сразу после этого и может не произойти вообще .
Более того, переменные могут существовать в течение длительного времени по многим причинам , например, распространяющееся исключение или самоанализ модуля могут поддерживать счетчик ссылок на переменную больше 0. Кроме того, переменная может быть частью цикла ссылок - CPython с включенной сборкой мусора чаще всего ломается. , но не все, такие циклы, да и то только периодически.
Поскольку у вас нет гарантии, что он будет выполнен, никогда не следует помещать код, который вам нужно запустить __del__()
- вместо этого этот код принадлежит finally
предложению try
блока или диспетчеру контекста в with
операторе. Тем не менее, существуют действительные случаи использования для __del__
: например , если объект X
ссылки , Y
а также хранит копию Y
справки в глобальном cache
( cache['X -> Y'] = Y
) , то это было бы вежливой для X.__del__
также удалить запись кэша.
Если вы знаете , что деструктор обеспечивает (в нарушение указанного выше ориентира) требуемой очистки, вы можете назвать это непосредственно , так как нет ничего особенного, как метод: x.__del__()
. Очевидно, вам следует делать это только в том случае, если вы знаете, что он не против, когда вам дважды позвонят. Или, в крайнем случае, вы можете переопределить этот метод, используя
type(x).__del__ = my_safe_cleanup_method
__exit__
в этом контексте? Это запускается после или до__del__
или вместе?__del__
методы могут не работать даже при завершении программы, и даже когда они запускаются при завершении, написание__del__
метода, который работает правильно, даже когда интерпретатор занят самоуничтожением вокруг вас, требует более тщательного кодирования, чем применяют многие программисты. (При очистке CPython__del__
методы обычно запускаются при завершении работы интерпретатора, но бывают случаи, когда этого недостаточно. Потоки демонов, глобальные переменные уровня C и объекты,__del__
созданные в другом,__del__
могут привести к тому, что__del__
методы не будут запущены.)Я написал ответ на другой вопрос, хотя это более точный вопрос.
Как работают конструкторы и деструкторы?
Вот несколько самоуверенный ответ.
Не используйте
__del__
. Это не C ++ или язык, созданный для деструкторов. Этот__del__
метод действительно должен быть исключен в Python 3.x, хотя я уверен, что кто-то найдет вариант использования, который имеет смысл. Если вам нужно использовать__del__
, помните об основных ограничениях на http://docs.python.org/reference/datamodel.html :__del__
вызывается, когда сборщик мусора собирает объекты, а не когда вы теряете последнюю ссылку на объект и не выполняетеdel object
.__del__
отвечает за вызов любого__del__
из суперкласса, хотя неясно, находится ли он в порядке разрешения методов (MRO) или просто вызывает каждый суперкласс.__del__
средства, позволяющего сборщику мусора отказываться от обнаружения и очистки любых циклических ссылок, например от потери последней ссылки на связанный список. Вы можете получить список игнорируемых объектов из gc.garbage. Иногда вы можете использовать слабые ссылки, чтобы полностью избежать цикла. Это время от времени обсуждается: см. Http://mail.python.org/pipermail/python-ideas/2009-October/006194.html .__del__
Функция может обмануть, сохраняя ссылку на объект, и остановить вывоз мусора.__del__
игнорируются.__del__
дополняет__new__
гораздо больше, чем__init__
. Это сбивает с толку. См. Http://www.algorithm.co.il/blogs/programming/python-gotchas-1- del -is-not-the-Against-of- init / для объяснения и ошибок.__del__
не является «любимым» ребенком Python. Вы заметите, что документация sys.exit () не указывает, собирается ли мусор перед выходом, и есть много странных проблем. Вызов__del__
глобальных переменных on вызывает странные проблемы с упорядочением, например http://bugs.python.org/issue5099 . Следует__del__
позвонить, даже если__init__
не удалось? См. Http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423 для длинного потока.Но с другой стороны:
__del__
означает, что вы не забываете вызывать закрытие заявления. См. Http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/ для профессиональной__del__
точки зрения. Обычно речь идет об освобождении ctypes или какого-либо другого специального ресурса.И моя личная причина не любить эту
__del__
функцию.__del__
то вспоминает, это превращается в тридцать сообщений о замешательстве.Итак, найдите причину не использовать
__del__
.источник
__del__
, а как звонить__del__
, ваш ответ интересен.__del__
Метод, он будет вызываться , когда объект мусора. Обратите внимание, что его вызов не обязательно гарантируется. Следующий код сам по себе не обязательно сделает это:Причина в том,
del
что счетчик ссылок просто уменьшается на единицу. Если что-то еще имеет ссылку на объект,__del__
он не будет вызван.Однако есть несколько предостережений при использовании
__del__
. Как правило, они обычно не очень полезны. Для меня это больше похоже на то, что вы хотите использовать метод close или, возможно, оператор with .См. Документацию Python по
__del__
методам .Еще одно замечание:
__del__
методы могут препятствовать сборке мусора при чрезмерном использовании. В частности, циклическая ссылка, имеющая более одного объекта с__del__
методом, не будет собираться сборщиком мусора. Это потому, что сборщик мусора не знает, какой из них вызвать первым. Дополнительную информацию см. В документации по модулю gc .источник
__del__
Метод (примечание правописание!) Вызывается , когда ваш объект окончательно разрушен. С технической точки зрения (в cPython) это происходит, когда на ваш объект больше нет ссылок, т.е. когда он выходит за пределы области видимости.Если вы хотите удалить свой объект и, таким образом, вызвать
__del__
метод, используйтекоторый удалит объект (при условии, что на него не было других ссылок).
Я предлагаю вам написать такой небольшой класс
И исследуйте интерпретатор Python, например
Обратите внимание, что jython и ironpython имеют разные правила относительно того, когда именно объект удаляется и
__del__
вызывается. Однако это не считается хорошей практикой__del__
из-за этого и того факта, что объект и его окружение могут находиться в неизвестном состоянии при его вызове. Это также не является абсолютно гарантированным__del__
вызовом - интерпретатор может выйти разными способами, не удаляя все объекты.источник
use del obj1
кажется, плохая идея полагаться.Как уже упоминалось ранее,
__del__
функциональность несколько ненадежна. В случаях, когда это может показаться полезным, рассмотрите возможность использования вместо них методов__enter__
и__exit__
. Это даст поведение, подобноеwith open() as f: pass
синтаксису, используемому для доступа к файлам.__enter__
автоматически вызывается при входе в область видимостиwith
, а__exit__
вызывается автоматически при выходе из нее. См. Этот вопрос для получения более подробной информации.источник