Временные ссылки автоматически очищаются в Python?
Это в основном вопрос о времени жизни временных. Если функция возвращает объект, но ссылка не назначена переменной и используется только для вызова метода в возвращенном объекте, автоматически очищается временная ссылка?
Чтобы привести конкретный пример, предположим, что есть цепочка вызовов методов:
o.method_a().method_b()
Временная ссылка возвращена o.method_a()
автоматически очищается при вызове method_b()
заканчивается, как если бы строка была написана так:
tmp = o.method_a()
try:
tmp.method_b()
finally:
tmp = None
РЕДАКТИРОВАТЬ: меня интересует общий ответ. CPython завершает объекты, как только число ссылок падает до 0. Другие реализации Python могут не завершать объекты сразу. Мне интересно, похож ли язык Python на C++, который гарантирует, что временные объекты уничтожаются в конце оператора, для которого они были созданы. (За исключением того, что в Python вопрос заключается в том, очищаются ли временные ссылки в конце оператора, для которого они были созданы.)
В C++ подобный код может быть реализован с помощью:
class B {
public:
void method_b();
};
class A {
public:
std::shared_ptr<B> method_a();
};
A o;
o.method_a()->method_b();
Стандарт C++ гласит: "Временные объекты уничтожаются как последний шаг в оценке полного выражения... который (лексически) содержит точку, в которой они были созданы. Это верно, даже если эта оценка заканчивается созданием исключения". В этом примере это означает, что временный std::shared_ptr<B>
объект, созданный при вызове A::method_a()
уничтожается сразу по окончании оценки полного выражения o.method_a()->method_b();
, Уничтожение std::shared_ptr
означает очистку ссылки на общий объект.
3 ответа
Да, сборщик мусора отвечает за отслеживание количества ссылок. Когда счетчик ссылок падает до нуля, сборщик мусора удаляет объект. Вот быстрый пример.
>>> class C(object):
... def foo(self):
... return B()
...
>>> class B(object):
... def __del__(self):
... print 'deleting %r' %self
... def bar(self):
... print 'I am method bar of %r' %self
...
>>> c = C()
>>> c.foo().bar()
I am method bar of <__main__.B object at 0xa187d2c>
deleting <__main__.B object at 0xa187d2c>
В качестве примечания: если есть ссылка на временный объект из какого-либо другого объекта, он не будет удален. Объект является мусором, только когда счетчик ссылок равен нулю.
Также заметка о del
, del
просто сбрасывает счетчик ссылок на объект. Это не удаляет объект. Например, если a = b = C()
, del a
удаляет только имя a и сбрасывает счетчик ссылок для объекта C()
, но на самом деле не удаляет его, потому что b
до сих пор относится к этому.
Вы правы, подсчет ссылок является реализацией CPython. Что касается других реализаций, спецификация Python не дает никаких гарантий относительно того, когда объекты уничтожаются.
Вот что говорит Python Language Reference по этому вопросу:
Объекты никогда не уничтожаются явно; однако, когда они становятся недоступными, они могут быть собраны мусором. Реализация может откладывать сборку мусора или вообще ее пропускать - вопрос качества реализации в том, как реализована сборка мусора, до тех пор, пока не будут собраны объекты, которые все еще доступны.
Что вы подразумеваете под "очищенным"? Вы могли бы иметь в виду очищенный, как в "деструкторе __del__
называется "или очищается, как в" связанная память освобождается ". Это не гарантировано. Например, вы можете сравнить CPython 2.7.2 с PyPy 1.7.0 [на примере @Praveen Gollakota]:
class C(object):
def foo(self):
return B()
class B(object):
def __del__(self):
print 'deleting %r' %self
def bar(self):
print 'I am method bar of %r' %self
c = C()
c.foo().bar()
print 'END OF LINE'
производит
localhost-2:coding $ python tempref.py
I am method bar of <__main__.B object at 0x1004b7d90>
deleting <__main__.B object at 0x1004b7d90>
END OF LINE
localhost-2:coding $ pypy tempref.py
I am method bar of <__main__.B object at 0x0000000102bc4cb0>
END OF LINE
Хороший вопрос.
Я предполагаю, что объект добавлен в сборщик мусора python из python, потому что у объекта нет ссылки. Затем это немедленно удаляется.