python 类和类属性什么时候被垃圾收集?

Mig*_*ght 5 python garbage-collection class class-attributes class-attribute

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"
Run Code Online (Sandbox Code Playgroud)

上面的代码在 Hidden.py 中,运行python Hidden.py会产生以下输出:

Member __init__ class mem
main
WithMembers __init__
<__main__.Member object at 0x935aeec>
Member __init__ instance mem
WithMembers __del__
Member __del__ instance mem
end
Run Code Online (Sandbox Code Playgroud)

除非我取消对其中一个语句的注释,否则我不会Member __del__ class mem在输出或class mem文件中看到del。为什么是这样?python 类和类属性什么时候被垃圾收集?

Mig*_*ght 5

这被报告为http://bugs.python.org/issue1545463中的错误,已在 3.4 中修复,但未向后移植(我运行的是 2.7)。http://code.activestate.com/lists/python-list/504216/中也对此进行了解释。请参阅下面的 python 3.5 输出。

基于上述,我的理解是,在 2.7 中,WithMembers当解释器退出时,新样式类仍然存在(没有被 GC 清理)。因此,classMem不会被垃圾回收,因为WithMembers仍然引用它。

请注意,新样式类具有对自身的循环引用__mro__和一些内置描述符(http://bugs.python.org/issue17950)。尽管模块级新式类在模块清理后被 GC 视为死亡,但在模块清理后清理它们的 GC 调用被禁用,因为它会导致太多其他问题。

这不会导致内存泄漏,因为操作系统会在解释器退出后清理资源。

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()
    print("end")
Run Code Online (Sandbox Code Playgroud)

运行时输出以下内容python3 Hidden.py

Member __init__ class mem
main
WithMembers __init__
<__main__.Member object at 0xb6fc8e2c>
Member __init__ instance mem
WithMembers __del__
Member __del__ instance mem
end
Member __del__ class mem
Exception ignored in: <bound method Member.__del__ of <__main__.Member object at 0xb6fc8e2c>>
Traceback (most recent call last):
  File "class_member_gc.py", line 8, in __del__
NameError: name 'open' is not defined
Run Code Online (Sandbox Code Playgroud)