Python3变量名称的简单区别可以改变代码的运行方式吗?

时间:2014-04-04 13:52:02

标签: python oop python-3.x finalizer

此代码......

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的东西。

1 个答案:

答案 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个密钥;这使得您观察到的行为更加随机,只是多次重新运行代码可能会或可能不会触发错误消息。