此代码......
class Person:
num_of_people = 0
def __init__(self, name):
self.name = name
Person.num_of_people += 1
def __del__(self):
Person.num_of_people -= 1
def __str__(self):
return 'Hello, my name is ' + self.name
cb = Person('Corey')
kb = Person('Katie')
v = Person('Val')
产生以下错误......
Exception AttributeError: "'NoneType' object has no attribute 'num_of_people'" in <bound method Person.__del__ of <__main__.Person object at 0x7f5593632590>> ignored
但是这段代码没有。
class Person:
num_of_people = 0
def __init__(self, name):
self.name = name
Person.num_of_people += 1
def __del__(self):
Person.num_of_people -= 1
def __str__(self):
return 'Hello, my name is ' + self.name
cb = Person('Corey')
kb = Person('Katie')
vb = Person('Val')
我看到的唯一区别是最后一个变量名称是“vb”与“v”。
我正在学习Python并正在研究OOP的东西。
答案 0 :(得分:59)
是的,虽然引起这种情况的变量名称不是那么多,而不是直接。
当Python退出时,所有模块也会被删除。清理模块的方法是将模块中的所有全局变量设置为None
(因此这些引用不再引用原始对象)。这些全局变量是字典对象中的键,并且由于字典是任意排序的,重命名一个变量可以改变变量被清除的顺序。
当您将v
重命名为vb
时,您更改了清除变量的顺序,现在最后清除Person
。
一种解决方法是在type(self).num_of_people -= 1
方法中使用__del__
代替:
def __del__(self):
type(self).num_of_people -= 1
因为实例将始终具有对该类的引用,或者测试Person
是否未设置为None
:
def __del__(self):
if Person is not None:
Person.num_of_people -= 1
两个注释:
根据Safe Object Finalization,CPython 3.4不再将全局变量设置为None
(在大多数情况下);见PEP 442。
CPython 3.3自动将randomized hash salt应用于str
字典中使用的globals
个密钥;这使得您观察到的行为更加随机,只是多次重新运行代码可能会或可能不会触发错误消息。