__del__上的Python attributeError

时间:2013-08-05 12:56:20

标签: python class attributeerror del

我有一个python类对象,我想分配一个类变量的值

class Groupclass(Workerclass):
    """worker class"""
    count = 0

    def __init__(self):
        """initialize time"""
        Groupclass.count += 1
        self.membercount = 0;
        self.members = []

    def __del__(self):
        """delte a worker data"""
        Groupclass.count -= 1


if __name__ == "__main__":
    group1 = Groupclass()

此执行结果是正确的,但有一条错误消息显示:

Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound method Groupclass.__del__ of <__main__.Groupclass instance at 0x00BA6710>> ignored

有人可以告诉我,我做错了吗?

2 个答案:

答案 0 :(得分:15)

您的__del__方法假定该类在被调用时仍然存在。

这个假设是不正确的。当您的Python程序退出并且现在设置为Groupclass时,None已被清除。

测试对该类的全局引用是否仍然存在:

def __del__(self):
    if Groupclass:
        Groupclass.count -= 1

或使用type()获取本地参考:

def __del__(self):
    type(self).count -= 1

但请注意,这意味着如果count被子类化,Groupclass的语义会发生变化(每个子类获得.count属性,而Groupclass只有.count属性)。

引用__del__钩子文档:

  

警告:由于调用__del__()方法的不稳定情况,将忽略执行期间发生的异常,并向sys.stderr打印警告。此外,当响应于被删除的模块而调用__del__()时(例如,当完成程序的执行时),__del__()方法引用的其他全局变量可能已经被删除或者在过程中被拆除(例如进口机械关闭)。因此,__del__()方法应该保持维持外部不变量所需的绝对最小值。从版本1.5开始,Python保证在删除其他全局变量之前,从其模块中删除名称以单个下划线开头的全局变量;如果不存在对此类全局变量的其他引用,这可能有助于确保在调用__del__()方法时导入的模块仍然可用。

如果您使用的是Python 3,则需要另外两个注意事项:

  • CPython 3.3自动将randomized hash salt应用于str字典中使用的globals个密钥;这也会影响清理全局变量的顺序,而可能只能在某些的运行中看到问题。

  • 根据Safe Object Finalization,CPython 3.4不再将全局变量设置为None(在大多数情况下);见PEP 442

答案 1 :(得分:1)

调用__del__()方法时,垃圾回收机制可能会恢复Groupclass,因此使用Groupclass.xxx可能会失败。但是您可以通过self.__class__.count访问count变量。代码如下:

def __del__(self):
    self.__class__.count -= 1