как скоро вызывается `__del__` после того, как счетчик ссылок падает до нуля? - PullRequest
4 голосов
/ 21 марта 2012

Как скоро после того, как счетчик ссылок достигнет нуля, будет вызван метод __del__?Обещает ли язык, что это сделано сразу же, прежде чем любой другой код использования сможет выполняться?Или каждая реализация может делать то, что ей нравится, потенциально задерживая вызов на __del__ произвольно долго?

Пожалуйста, игнорируйте ситуацию, когда программа собирается завершить работу (я предполагаю, что это означает, что последний оператор в данном блоке имеетзакончено, и стек пуст).Я понимаю, что в таких случаях нет никаких обещаний о __del__;это может даже не называться вообще.

Кроме того, я знаю, что счетчик ссылок может быть ненулевым из-за циклов и т. Д. Я не беспокоюсь об этом здесь (я задаю отдельный вопрос об этом).

Ответы [ 3 ]

11 голосов
/ 21 марта 2012

Python не дает никаких гарантий относительно того, когда вызывается __del__, или , вызывается ли он вообще .Как таковые, методы __del__ вряд ли будут вызваны, если объект является частью ссылочного цикла, потому что даже если цикл в целом очищен, Python не может решить, где прерывать цикл и в каком порядке__del__ методы (если таковые имеются) должны быть вызваны.Из-за довольно странной семантики __del__ (чтобы вызвать __del__, счетчик объекта временно увеличивается, а метод __del__ может предотвратить разрушение объекта путем сохранения ссылки где-то еще), что происходит в другомРеализация это что-то вроде броского удара.(Я не помню точных деталей в текущем Jython, но в прошлом он несколько раз менялся.)

Тем не менее, в CPython , если вызывается __del__,он вызывается, как только счетчик ссылок падает до нуля (поскольку пересчет является единственным способом вызова методов __del__, и единственный шанс, что CPython вызывает __del__, - это когда фактический счетчик изменений изменяется.)

5 голосов
/ 21 марта 2012

О единственной причине, по которой вы должны использовать __del__, - помочь сборщику мусора собрать больше мусора.Например, если вы реализуете что-то вроде модуля ctypes, который присоединяет разделяемые библиотеки к запущенному процессу, имеет смысл выгружать эти библиотеки, когда собрана последняя ссылка на него, чтобы его адресное пространство могло использоваться для чего-то другого..

Для управления другими видами ресурсов вы почти наверняка не хотите иметь ничего общего с сборщиком мусора.Правильный инструмент для этого - контекстные менеджеры .В отличие от языков, таких как C ++ или Ada, где для RAII используется переменная область действия, python использует оператор with вместе с объектом, который имеет методы __enter__ и __exit__.Многие встроенные типы Python используют этот точный механизм, чтобы удостовериться, что шаги завершения действительно выполняются:

>>> x = file("foo", 'w')
>>> x.closed
False
>>> with x:
...     x.write("bar")
... 
>>> x.closed
True

Это также ценно с точки зрения дзен питона:

Явное лучше, чем неявное.

, потому что ясно, что происходит очистка, оно явно написано именно так.Это намного лучше, чем случай, когда очистка происходит «волшебным образом», когда какая-то скрытая переменная (счетчик ссылок, если он существует, а в PyPy, IronPython или Jython) не достигает определенного значения, может быть.

3 голосов
/ 21 марта 2012

Пожалуйста, прочитайте CPython object.__del__ документы.Это говорит о большей части того, что нужно сказать, но зависит от конкретной реализации;большинство других реализаций Python не используют refcounting, и поэтому вы не должны зависеть от того, вызывается ли он в то или иное время (или даже вообще) для функциональности.Он вызывается во время уничтожения, что зависит от реализации.

...