Временные ссылки автоматически очищаются в Python? - PullRequest
5 голосов
/ 28 января 2012

Это в основном вопрос о времени жизни временных. Если функция возвращает объект, но ссылка не назначена переменной и используется только для вызова метода в возвращенном объекте, автоматически очищается временная ссылка?

Чтобы привести конкретный пример, предположим, что есть цепочка вызовов методов:

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 ]

3 голосов
/ 28 января 2012

Да, сборщик мусора отвечает за отслеживание количества ссылок. Когда счетчик ссылок падает до нуля, сборщик мусора удаляет объект. Вот быстрый пример.

>>> 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 должен сказать по этому поводу:

Объекты никогда не уничтожаются явно; однако, когда они становятся недоступными, они могут быть собраны мусором. Реализация может откладывать сборку мусора или вообще ее опускать - вопрос качества реализации в том, как реализована сборка мусора, до тех пор, пока не будут собраны объекты, которые все еще доступны.

2 голосов
/ 28 января 2012

Что вы подразумеваете под «очищенным»? Вы можете иметь в виду очищенный, как в «вызывается деструктор __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
0 голосов
/ 28 января 2012

Хороший вопрос.

Я полагаю, что объект добавлен в сборщик мусора python из python, потому что объект не имеет ссылки. Тогда это немедленно удаляется.

...