См. 10 подсказок относительно записи повторно используемого кода для некоторой справки.
__ del __
- финализатор . Он вызывается, когда объект собирает мусор , что происходит в какой-то момент после удаления всех ссылок на объект.
В простом случае это может быть сразу после того, как вы скажете del x
или, если x
- локальная переменная, после завершения функции. В частности, если нет циклических ссылок, CPython (стандартная реализация Python) немедленно выполняет сборку мусора.
Однако это деталь реализации CPython. Единственное требуемое свойство сборки мусора Python - это то, что это происходит после удаления всех ссылок, поэтому это может не происходить сразу после , а может вообще не происходить .
Более того, переменные могут существовать долгое время по многим причинам , например, распространяющееся исключение или самоанализ модуля могут поддерживать счетчик ссылок на переменную больше нуля. Кроме того, переменная может быть частью цикл ссылок - CPython с включенной сборкой мусора прерывает большинство, но не все, такие циклы, и даже то только периодически.
Поскольку у вас нет гарантии, что он выполняется, нельзя никогда ставить код, который необходимо запустить в __ del __ ()
- вместо этого этот код принадлежит предложению finally
блока try
или диспетчеру контекста в с заявлением
. Однако, существуют допустимые варианты использования для __ del __
: например, если объект X
ссылается на Y
, а также сохраняет копию Y
в глобальном кэше
( cache ['X -> Y'] = Y
), то было бы вежливо, если бы X .__ del __
также удалили запись в кэше.
Если вы знаете , что деструктор обеспечивает (в нарушение приведенного выше правила) необходимую очистку, вы можете вызвать его напрямую , поскольку в нем нет ничего особенного как метод: x .__ del __ ()
. Очевидно, вам следует делать это только в том случае, если вы знаете, что он не против, когда вам дважды позвонят. Или, в крайнем случае, вы можете переопределить этот метод, используя
type(x).__del__ = my_safe_cleanup_method
Метод __ del __
, он будет вызываться при сборке мусора. Обратите внимание, что его вызов не обязательно гарантируется. Следующий код сам по себе не обязательно сделает это:
del obj
Причина в том, что del
просто уменьшает счетчик ссылок на единицу. Если что-то еще имеет ссылку на объект, __ del __
не будет вызван.
Однако есть несколько предостережений при использовании __ del __
. Как правило, они обычно не очень полезны. Для меня это больше похоже на то, что вы хотите использовать метод close или, может быть, с оператором .
См. документацию python в __ del __
методах .
Еще одно замечание: методы __ del __
могут препятствовать сборке мусора при чрезмерном использовании. В частности, циклическая ссылка, которая имеет более одного объекта с методом __ del __
, не будет собираться сборщиком мусора. Это потому, что сборщик мусора не знает, какой из них вызвать первым. Дополнительную информацию см. В документации по модулю gc .
Метод __ del __
(обратите внимание на правописание!) вызывается, когда ваш объект окончательно уничтожается. С технической точки зрения (в cPython), когда на ваш объект больше нет ссылок, т.е. когда он выходит за пределы области видимости.
Если вы хотите удалить свой объект и, таким образом, вызвать метод __ del __
, используйте
del obj1
, который удалит объект (при условии, что на него не было других ссылок).
Я предлагаю вам написать небольшой класс вроде этого
class T:
def __del__(self):
print "deleted"
И исследовать его в интерпретаторе python, например
>>> 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
>>>
Обратите внимание, что jython и ironpython имеют разные правила относительно того, когда именно удаляется объект и __ del __
называется. Использование __ del __
не считается хорошей практикой, хотя из-за этого и того факта, что объект и его окружение могут находиться в неизвестном состоянии при его вызове. Абсолютно не гарантируется, что __ del __
также будет вызван - интерпретатор может выйти разными способами без удаления всех объектов.
__ del __
, хотя из-за этого и того факта, что объект и его окружение могут находиться в неизвестном состоянии при его вызове. Абсолютно не гарантируется, что __ del __
также будет вызван - интерпретатор может выйти разными способами без удаления всех объектов. Считается хорошей практикой использовать __ del __
, хотя из-за этого и того факта, что объект и его окружение могут находиться в неизвестном состоянии при его вызове. Абсолютно не гарантируется, что __ del __
также будет вызван - интерпретатор может выйти разными способами без удаления всех объектов. Я написал ответ на другой вопрос, хотя это более точный вопрос.
Как работают конструкторы и деструкторы?
Вот несколько самоуверенный ответ.
Не используйте __ del __
. Это не C ++ или язык, созданный для деструкторов. Метод __ del __
действительно должен быть убран в Python 3.x, хотя я уверен, что кто-то найдет вариант использования, который имеет смысл.Если вам нужно использовать __ del __
, помните об основных ограничениях для http://docs.python.org/reference/datamodel.html :
__del__
is вызывается, когда сборщик мусора собирает объекты, а не когда вы теряете последнюю ссылку на объект и не когда выполняете 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-противоположность- init / для объяснения и ошибок. __ del __
не «любимый» ребенок в Python. Вы заметите, что sys.В документации exit () не указывается, собирается ли мусор перед выходом, и есть много странных проблем. Вызов __ del __
на глобальных объектах вызывает странные проблемы с упорядочением, например, 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 __
.