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

Cor*_*rey 51 python oop finalizer python-3.x

这段代码......

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

产生以下错误......

Exception AttributeError: "'NoneType' object has no attribute 'num_of_people'" in <bound method Person.__del__ of <__main__.Person object at 0x7f5593632590>> ignored
Run Code Online (Sandbox Code Playgroud)

但是这段代码没有.

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

我看到的唯一区别是最后一个变量名称是"vb"与"v".

我正在学习Python并正在研究OOP的东西.

Mar*_*ers 59

是的,虽然它不是导致这个的变量名称,而不是直接.

当Python退出时,所有模块也会被删除.清理模块的方法是将模块中的所有全局变量设置为None(因此这些引用不再引用原始对象).这些全局变量是字典对象中的键,并且由于字典是任意排序的,因此重命名一个变量可以更改变量清除的顺序.

当您重命名vvb,你改变了哪些变量被清除,现在的顺序Person是最后的清除.

一种解决方法是type(self).num_of_people -= 1__del__方法中使用:

def __del__(self):
    type(self).num_of_people -= 1
Run Code Online (Sandbox Code Playgroud)

因为实例将始终具有对类的引用,或者测试if Person是否设置为None:

def __del__(self):
    if Person is not None:
        Person.num_of_people -= 1
Run Code Online (Sandbox Code Playgroud)

两个笔记:

  • None根据安全对象终结,CPython 3.4不再将全局变量设置为(在大多数情况下); 见PEP 442.

  • CPython 3.3自动将随机哈希盐str应用于globals字典中使用的键; 这使得您观察到的行为更加随机,只是多次重新运行代码可能会或可能不会触发错误消息.

  • @aIKid:当Python退出时,(或者如果通过删除对它的所有引用并从`sys.modules`中删除它来删除模块,但通常不会这样做),则调用模块`__del __,然后先进行通过将名称重新绑定到"无"来清除模块中的所有全局变量. (3认同)
  • @sds:终结很挑剔; 通过将全局变量设置为"无",可以正确地破坏许多常见的循环引用,而无需调用"globals"字典的(缓慢且完全不需要的)调整大小.最终确实为Python 3.4找到了更好的方法,所以整个问题不再是该版本的问题. (3认同)
  • 呃..答案很棒,但我真的不明白这一点.什么是'在intepreter退出'是什么意思?你能解释一下吗? (2认同)
  • @Corey:这里没有更高的水平; 最重要的是,在最终确定期间,像`Person`和`v`和`vb`这样的全局变量都为它们分配了`None`,所以你不能指望`Person`仍然是`__del__`中的类. (2认同)