Сброс / перезагрузка атрибутов класса вложенного класса во время выполнения - PullRequest
1 голос
/ 15 марта 2019

Я использую вложенный класс для целей бухгалтерского учета в Python 3. Структура класса (очень упрощенная) выглядит примерно так:

class BookKeeping:

    class ItemA:
        count = 0
        item_list = []

        @classmethod
        def add(cls, item_a):
            cls.count += 1
            cls.item_list.append(item_a)

    class ItemB:
        count = 0
        item_dict = {}

        ...

Этот класс позволяет отслеживать и получать доступ к некоторым "глобальным" свойствам системы, которую я моделирую. Наличие вложенных классов обеспечивает свободное пространство имен. Например, в любом модуле я могу ... import BookKeeping as BK и проверить, сколько ItemB объектов (BK.ItemB.count).

В какой-то момент в моей программе я хотел бы "сбросить" все атрибуты класса, т. Е. Я бы хотел снова установить BookKeeping.ItemA.count в 0 и очистить списки и словари и т. Д.

Очевидно, я мог бы добавить метод класса верхнего уровня, например BookKeeping.reset(), который сбрасывает все значения «вручную», например:

class BookKeeping:

    @classmethod
    def reset(cls):
        cls.ItemA.count = 0
        cls.ItemA.item_list = []
        cls.ItemB.count = 0

        ...

Однако, мне кажется, что этот подход подвержен ошибкам и включает в себя «обслуживание» этого класса (я мог бы забыть сбросить некоторые атрибуты). Обратите внимание, что мой реальный класс сложнее, чем пример, который я привел.

Какой самый простой способ вернуть все атрибуты класса в исходное состояние во время выполнения?

1 Ответ

2 голосов
/ 15 марта 2019

Итак, заранее: должны ли вы этим заниматься? Вероятно, нет.

Я бы посоветовал вам переосмыслить структуру ваших проектов, поскольку глобальное состояние - это то, чего обычно следует избегать.

Если вы все еще хотите сделать это, хотя ...

Осторожно, впереди немного непроверенной (!) Магической магии:

import copy

class BookKeeping(object):
    __backup = {}

    class ItemA(object):
        ...

    class ItemB(object):
        ...

    @classmethod
    def reset(cls):
        for name, backup in cls.__backup.items():
            inner_cls = getattr(cls, name)
            for k, v in backup.items():
                setattr(inner_cls, k, copy.deepcopy(v))

for i in dir(BookKeeping):
    if not i.startswith("_"):
        obj = getattr(BookKeeping, i)
        BookKeeping.__backup[i] = {k: copy.deepcopy(getattr(obj, k)) for k in dir(obj)}

Дополнительные примечания. Обычно это сложная проблема. Но вы могли бы использовать ту же технику и для других структур вложенности, и обрабатывать типы по-другому, а не по-другому на первом уровне.

Это проблема, потому что вы не хотите deepcopy сами типы, поскольку это дублирует состояние всех живых объектов в то время и всех новых объектов вместе с текущим новым глобальным состоянием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...