Нет, в Python вы должны использовать Context Managers :
class ResourceWrapper:
def __init__(self):
...
...
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self._close(manual_close=False)
with ResourceWrapper() as wrapper:
# do something with wrapper
Примечание 1: Этот комментарий есть в _close()
метод:
Это означает, что _close
вызывается GC, self._python_resource
может быть
уже GCed, но мы не знаем наверняка, поэтому мы ничего не делаем и полагаемся на
GC бесплатно self._python_resource
.
Я не уверен, что вы подразумеваете под этим, но пока вы держите ссылку на объект (и если это не слабая ссылка ), это не будет GC ' ред.
Примечание 2: Что произойдет, если объект, являющийся диспетчером контекста, используется без блока with
? Тогда ресурс будет освобожден, когда объект будет собран мусором - но я бы не стал беспокоиться об этом. Использование менеджеров контекста - распространенная идиома в python (см. Любой пример с файлом open()
ing). Если это важно для вашего приложения, вы можете получить ресурсы в __enter__()
, таким образом, вы не получите, если не в блоке with
.
Примечание 3, о циклических ссылках: Если у вас есть два объекта, которые содержат ссылку друг на друга, вы сформировали циклическую ссылку, так что два объекта не будут освобождены «обычной» ссылкой. считая GC. Вместо этого они должны собираться поколением ГК, , если только не будет иметь метод __del__
. __del__
запрещает GC собирать предметы. См gc.garbage
:
Список объектов, которые коллекционер счел недоступными, но
не может быть освобожден (не коллекционируемые объекты). По умолчанию этот список
содержит только объекты с __del__() methods
. [1] Объекты, которые имеют
__del__()
методы и являются частью эталонного цикла, что делает весь эталонный цикл не подлежащим сбору, включая объекты не обязательно
в цикле, но достижимо только из него.
Представлен Python 3.4 PEP-442 , который вводит безопасное завершение объекта. В любом случае, у вас не будет недействительных ссылок. Если у вас есть атрибут (hasattr(self, "_python_resource")
), он будет действителен.
Еда на вынос: не используйте __del__
.