Каковы варианты использования python 3 для написания пользовательского метода __del__
или использования одного из stdlib 1? То есть, в каком сценарии он разумно безопасен и может сделать что-то, что трудно сделать без него?
По многим причинам (1 2 3 4 5 6), обычно рекомендуется избегать __del__
и вместо этого использовать контекстные менеджеры или выполнять очистку вручную:
-
__del__
не может быть вызван, если объекты живы на выходе intrepreter 2. - В точке ожидают, что объект может быть уничтожен, количество ссылок может фактически быть ненулевым (например, ссылка может выжить через кадр трассировки, удерживаемый вызывающей функцией). Это делает время разрушения гораздо более неопределенным, чем подразумевается простая непредсказуемость
gc
. - Сборщик мусора не может избавиться от циклов, если они включают более одного объекта с
__del__
- Код внутри
__del__
должен быть написан супер тщательно:- атрибуты объектов, установленные в
__init__
, могут отсутствовать, так как__init__
может вызвать исключение; - исключения игнорируются (печатаются только на
stderr
); - globals могут быть недоступны.
- атрибуты объектов, установленные в
Update:
PEP 442 значительно улучшил поведение __del__
. Кажется, что мои баллы 1-4 все еще действительны?
Обновление 2:
Некоторые из лучших библиотек python охватывают использование __del__
в питоне post-PEP 442 (то есть, python 3.4+), Я предполагаю, что моя точка 3 больше не действует после PEP 442, а остальные точки принимаются как неизбежная сложность завершения объекта.
1 Я расширил вопрос только от написания пользовательского метода __del__
, включив в него __del__
из stdlib.
2 Кажется, что __del__
всегда вызывается на выходе интерпретатора в более поздних версиях Cpython (есть ли у кого-нибудь встречный пример?). Однако для целей __del__
usablity не имеет значения: документы явно не дают никаких гарантий относительно этого поведения, поэтому нельзя полагаться (он может измениться в будущих версиях, и он может отличаться у не-CPython-переводчиков).