何时对python类和类属性进行垃圾收集?

2024-09-30 10:37:31 发布

您现在位置:Python中文网/ 问答频道 /正文

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会产生以下输出:

^{pr2}$

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


Tags: selfobjectinitmaindefmemclassend
2条回答

classMem是类WithMembers的一个类变量,这意味着它将被这个类的所有实例共享。在Python中,这是一个全局性的问题。 这就是为什么退出程序时没有调用类成员的__del__。在

这里有一个问题:为什么Python在退出程序时不简单地将所有引用计数设置为0,以便调用所有__del__函数?在

类似C++,它保证调用全局变量的析构函数。在Python中保证这一点的唯一方法是运行所有模块并删除它们的所有变量。但这意味着__del__方法不能相信它可能要使用的任何全局变量仍然存在,因为无法知道要以什么顺序删除变量。在

有两种方法可以强制销毁classMem。在

一个是del WithMembers.classMem。这将减少对0的引用计数,并且将自动调用__del__。在

另一个是使类WithMembers成为一个旧样式的类(不是从object继承的)。像这样:

...

class WithMembers:
    def __init__(self):
        print "WithMembers __init__"
        print WithMembers.classMem
        self.instanceMem = Member("instance mem")
...        

输出将是:

^{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调用被禁用,因为这会导致太多其他问题。在

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

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")

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

^{pr2}$

相关问题 更多 >

    热门问题