Python attributeError on __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 (в большинстве случаев), согласно завершению Safe Object; см. PEP 442.

Когда __del__()вызванный метод, Groupclass может быть восстановлен с помощью механизма сборки мусора, поэтому использование Groupclass.xxx может завершиться ошибкой. Но вы можете получить доступ к переменной count черезself.__class__.count. Код нравится ниже:

def __del__(self):
    self.__class__.count -= 1
Другие вопросы по тегам