为啥 Python 在对象之前销毁类变量?
Posted
技术标签:
【中文标题】为啥 Python 在对象之前销毁类变量?【英文标题】:Why does Python destroy class variables before objects?为什么 Python 在对象之前销毁类变量? 【发布时间】:2013-03-02 07:37:24 【问题描述】:我了解 Python 不保证程序结束时对象的销毁顺序,甚至不保证会发生。
所以我明白一个类的析构函数不能依赖全局变量,包括其他模块。
但我会认为类的对象必须在类被销毁之前被销毁。显然不是:
class A(object):
count = 0
def __init__(self):
A.count += 1
print 'Creating object, there are now', A.count
def __del__(self):
A.count -= 1
print 'Destroying object, there are now', A.count
a1 = A()
a2 = A()
在 Windows 7 x64 Python v2.7.3 上,我得到:
Creating object, there are now 1
Creating object, there are now 2
Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound
method A.__del__ of <__main__.A object at 0x0234B8B0>> ignored
Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound
method A.__del__ of <__main__.A object at 0x0234BE90>> ignored
我了解How do I correctly clean up a Python object? 的含义。但这种情况适用于类(我的 C++ 朋友的共享或“静态”)变量。实例肯定有对类变量的引用,不应该先销毁它,因为我们还有对它的引用?
在该类的对象之前销毁该类是问题还是错误? 也许我的问题是“类共享变量实际存储在哪里?”
(是的,我知道这可以使用上下文管理器来纠正,甚至可以简单地纠正:
del a1
del a2
在类被销毁之前销毁对象。)
【问题讨论】:
【参考方案1】:也许我的问题是“类共享变量实际存储在哪里?”
如果这是你的问题,答案是“在课堂上”。
解决您更大的问题:正如您所指出的,__del__
不能依赖全局变量 - 但 A
是全局变量,因此您不能依赖它。有趣的是,我在文档中找不到对此的官方声明,但互联网上有各种参考资料表明__del__
不能使用全局变量。 Here是一:
当 Python 程序终止时,每个模块中的全局变量都设置为 None。发生这种情况的顺序未定义
如果您通过self.__class__.count
而不是A.count
访问计数,它将起作用。 (这也是你使用self.count
时它起作用的原因。)
【讨论】:
实例上的.__class__
怎么样?
@FatalError:你是对的,参考问题是一个红鲱鱼。问题不在于类本身已被删除,而是引用它的全局变量已设置为无。我编辑了我的答案。
奇怪的是,当我尝试使用 .__class__
时,我得到了相同的行为。在这种情况下,它似乎在调用__del__
之前也设置为None
,这有点令人惊讶。
@FatalError:您是否将-=
和print
都更改为使用self.__class__
?我以为我也看到了你所看到的,但我还在做print A.count
。
通过环境设置PYTHONVERBOSE=2
可以看到模块清理和属性清理的顺序。以上是关于为啥 Python 在对象之前销毁类变量?的主要内容,如果未能解决你的问题,请参考以下文章
java中静态成员变量、实例变量、局部变量何时创建、何时销毁?
JAVA类与对象---实例变量与类变量的区别,实例方法和类方法的区别