5

这基本上是一个关于临时工寿命的问题。如果函数返回一个对象,但是引用并没有赋值给变量,只是用来调用返回对象的方法,临时引用会自动清除吗?

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

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()会在 full-expression 的计算结束时立即销毁o.method_a()->method_b();。销毁 astd::shared_ptr意味着清除对共享对象的引用。

4

3 回答 3

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只是减少对象的引用计数。它不会删除对象。例如, ifa = b = C()del a删除名称 a 并删除 object 的引用计数C(),但并没有真正删除它,因为b仍然引用它。

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

这就是Python 语言参考对此事的看法:

对象永远不会被显式销毁;但是,当它们变得无法访问时,它们可能会被垃圾收集。允许实现推迟垃圾收集或完全忽略它——只要没有收集仍然可访问的对象,垃圾收集的实现方式就是实现质量的问题。

于 2012-01-28T16:06:50.693 回答
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
于 2012-01-28T16:14:38.277 回答
0

好问题。

我想该对象已添加到 python 的垃圾收集器 od python中,因为该对象没有引用。然后立即删除。

于 2012-01-28T16:10:56.717 回答