是否在Python中自动清除临时引用?

时间:2012-01-28 15:57:56

标签: python reference temporary-objects language-details

这基本上是关于临时生活的问题。如果函数返回一个对象,但该引用未分配给变量并且仅用于调用返回对象上的方法,那么临时引用是否会自动清除?

举一个具体的例子,假设有一系列方法调用:

o.method_a().method_b()

o.method_a()的调用完成时,method_b()返回的临时引用是否自动清除,就好像该行写成:

tmp = o.method_a()
try:
    tmp.method_b()
finally:
    tmp = None

编辑:我对一般答案感兴趣。一旦引用计数降至0,CPython就会终止对象。其他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 个答案:

答案 0 :(得分: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对此事所说的话:

  

永远不会明确销毁对象;然而,当它们变得无法到达时,它们可能被垃圾收集。允许实现推迟垃圾收集或完全省略垃圾收集 - 只要没有收集到仍然可以访问的对象,实现垃圾收集的实现方式就是如此。

答案 1 :(得分:2)

“清除”是什么意思?您可以在“析构函数__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

答案 2 :(得分:0)

好问题。

我认为该对象被添加到python的garbage collector od python,因为该对象没有引用。然后立即将其删除。