class Member(object):
def __init__(self, identifier):
self.identifier = identifier
print "Member __init__", self.identifier
def __del__(self):
print "Member __del__", self.identifier
with open("/home/might/" + self.identifier, "w") as outF:
outF.write(self.identifier)
class WithMembers(object):
def __init__(self):
print "WithMembers __init__"
print WithMembers.classMem
self.instanceMem = Member("instance mem")
def __del__(self):
print "WithMembers __del__"
classMem = Member("class mem")
if __name__ == "__main__":
print "main"
WithMembers()
#del WithMembers.classMem # "Member __del__ class mem" before "end"
#del WithMembers # "Member __del__ class mem" after "end"
print "end"
上面的代码在隐藏.py运行python Hidden.py
会产生以下输出:
除非我取消了对del
语句的注释,否则在输出或class mem
文件中看不到Member __del__ class mem
。为什么会这样?何时对python类和类属性进行垃圾收集?在
classMem
是类WithMembers
的一个类变量,这意味着它将被这个类的所有实例共享。在Python中,这是一个全局性的问题。 这就是为什么退出程序时没有调用类成员的__del__
。在这里有一个问题:为什么Python在退出程序时不简单地将所有引用计数设置为0,以便调用所有
__del__
函数?在类似C++,它保证调用全局变量的析构函数。在Python中保证这一点的唯一方法是运行所有模块并删除它们的所有变量。但这意味着
__del__
方法不能相信它可能要使用的任何全局变量仍然存在,因为无法知道要以什么顺序删除变量。在有两种方法可以强制销毁
classMem
。在一个是
del WithMembers.classMem
。这将减少对0的引用计数,并且将自动调用__del__
。在另一个是使类
WithMembers
成为一个旧样式的类(不是从object
继承的)。像这样:输出将是:
^{pr2}$这里有一个非常有用的链接,可以帮助你更好地理解这个答案。 http://www.electricmonk.nl/log/2008/07/07/python-destructor-and-garbage-collection-notes/
希望有帮助。:)
据报道,这是在3.4中修复的http://bugs.python.org/issue1545463中的一个错误,但没有后端口(我运行的是2.7)。这在http://code.activestate.com/lists/python-list/504216/中也有解释。Python3.5的输出见下文。在
基于以上,我的理解是,在2.7中,当解释器退出时,新样式类
WithMembers
仍然存在(没有被GC清理)。因此,classMem
没有被垃圾回收,因为WithMembers
仍然引用它。在请注意,新的样式类具有来自
__mro__
和一些内置描述符(http://bugs.python.org/issue17950)的循环引用。即使模块级的新样式类在模块清理之后被GC认为是死的,但是在模块清理之后清理它们的GC调用被禁用,因为这会导致太多其他问题。在这不会导致内存泄漏,因为在解释器退出后,操作系统会清理资源。在
使用
^{pr2}$python3 Hidden.py
运行时输出以下内容:相关问题 更多 >
编程相关推荐