Атрибут PythonError на __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

Может кто-нибудь сказать мне, что я сделал неправильно?

Ответ 1

Ваш метод __del__ предполагает, что класс все еще присутствует к моменту его вызова.

Это предположение неверно. Groupclass уже очищен, когда ваша программа Python завершена и теперь установлена ​​на 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 автоматически применяет рандомизированную хэш-соль к клавишам str, используемым в словаре globals; это также влияет на порядок, в котором очищаются глобалы, и может быть, что вы видите проблему только на некоторых прогонах.

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