Может ли простая разница в именах переменных Python3 изменить способ выполнения кода? [дубликат]


этот вопрос уже есть ответ здесь:

  • Python attributeError на _ _ del__ 1 ответ

этот код...

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 " против "в."

Я опираюсь на Python и сейчас работаю над материалом ООП.

1   51  

1 ответ:

да, хотя это не так много имя переменной, которая вызывает это, не напрямую.

когда Python выходит, все модули также удаляются. Способ очистки модулей заключается в установке всех глобалов в модуле на None (Так что эти ссылки больше не относятся к исходным объектам). Эти глобалы являются ключами в объекте словаря, и поскольку словари упорядочены произвольно, переименование одной переменной может изменить порядок, в котором переменные очищаются.

когда вы переименовали v до vb, вы изменили порядок, в котором переменные очищаются, и теперь Person снят последним.

один обход заключается в использовании type(self).num_of_people -= 1 на способ:

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

потому что экземпляр всегда будет иметь ссылку на класс еще, или проверить, если Person не установлено None:

def __del__(self):
    if Person is not None:
        Person.num_of_people -= 1

два замечания:

  • CPython 3.4 больше не устанавливает глобалы в None (в большинстве случаев), а Пер Завершение Безопасного Объекта; см. PEP 442.

  • CPython 3.3 автоматически применяет a рандомизированных хэш-соль до str ключи, используемые в globals словарь; это делает поведение вы наблюдали еще более случайным, просто повторное выполнение кода несколько раз может или не может вызвать сообщение об ошибке.