这基本上是关于临时生活的问题。如果函数返回一个对象,但该引用未分配给变量并且仅用于调用返回对象上的方法,那么临时引用是否会自动清除?
举一个具体的例子,假设有一系列方法调用:
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
意味着清除对共享对象的引用。
答案 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,因为该对象没有引用。然后立即将其删除。