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

在Python中是否自动清除临时引用?,python,reference,temporary-objects,language-details,Python,Reference,Temporary Objects,Language Details,这基本上是一个关于临时工寿命的问题。如果函数返回一个对象,但引用未分配给变量,仅用于调用返回对象上的方法,临时引用是否自动清除 为了给出一个具体的示例,假设存在以下方法调用链: o.method_a().method_b() 调用method\u b()完成时,o.method\u a()返回的临时引用是否自动清除,就好像该行是这样写的: tmp = o.method_a() try: tmp.method_b() finally: tmp = None 编辑:我对一般答案感

这基本上是一个关于临时工寿命的问题。如果函数返回一个对象,但引用未分配给变量,仅用于调用返回对象上的方法,临时引用是否自动清除

为了给出一个具体的示例,假设存在以下方法调用链:

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

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();
B类{
公众:
无效方法_b();
};
甲级{
公众:
std::shared_ptr方法_a();
};
A o;
o、 方法a()->方法b();

C++标准声明“临时对象被破坏为评估完整表达式的最后一步……(词汇)包含了它们创建的点。即使在结束异常时,也会发生异常。”这意味着调用

A::method_A()
创建的临时
std::shared_ptr
对象将在对完整表达式
o.method_A()->method_b()求值结束时立即销毁。销毁std::shared\u ptr意味着清除对共享对象的引用。

是的,垃圾收集器负责跟踪引用计数。当引用计数降至零时,垃圾收集器将删除该对象。下面是一个简单的例子

>>> 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>
>>C类(对象):
...     def foo(self):
...          返回B()
... 
>>>B类(对象):
...     定义(自我):
...         打印“正在删除%r”%self
...     def bar(自):
...         打印%r“%self”的“我是方法栏”
... 
>>>c=c()
>>>c.foo().bar()
我是方法吧
删除
作为旁注,如果有来自任何其他对象的对临时对象的引用,那么它不会被删除。仅当引用计数为零时,才会对对象进行垃圾收集

还有一个关于
del
的注释
del
只是删除对象的引用计数。它不会删除对象。例如,如果
a=b=C()

没错,引用计数是CPython实现。就其他实现而言,Python规范并没有提供任何关于对象何时被销毁的保证

关于这件事,我必须这样说:

物体永远不会被明确摧毁;但是,当它们变得无法访问时,可能会被垃圾收集。一个实现可以推迟垃圾收集或完全忽略垃圾收集——只要没有收集到仍然可以访问的对象,垃圾收集是如何实现的是实现质量的问题

好问题

我假设该对象被添加到python中,因为该对象没有引用。然后立即将其删除。

您所说的“清除”是什么意思?您可以表示清除,如“调用析构函数
\uu del\uu
”,或清除,如“释放关联内存”。两者都不能保证。例如,您可以将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
localhost-2:coding$python tempref.py
我是方法吧
删除
行尾
localhost-2:编码$pypy tempref.py
我是方法吧
行尾

通过“清除”引用,我的意思是使引用对象不再可通过保存引用的变量访问,例如通过赋值
None
或应用
del
。只要没有对对象的“活动”引用,GC就可以收集该对象。GC在终结过程中调用对象的
\uuu del\uuu()
方法。“GC在终结过程中调用对象的\uuu del\uuuu()方法。”也许我应该更明确一点:上面代码段的要点是不能保证调用
\uu del\uuuuu
。[或者,取决于你如何定义事物,我想不是所有的对象都是最终确定的。]+1我想它没有明确指定。感谢您的链接。您的两个代码段具有相同的语义,但并不是说其中任何一个都会立即调用终结器或销毁对象。事实上,即使在CPython中,如果对象处于一个循环中,销毁也可能会延迟(尽管您当时无法拥有终结器)。