Устарел класс для свойств словаря python - PullRequest
0 голосов
/ 06 мая 2020

В python у меня есть класс, один из его атрибутов - это какой-то другой класс, который содержит данные, например:

class A:
    class Params:
        def __init__(self):
            self.param1 = None
            self.param2 = None
            ...

    def __init__(self):
        self.parameters = self.Params()

Таким образом, если кто-то хочет изменить один из параметров в self.parameters он может написать self.parameters.param1 = ....

Я хочу изменить класс Params, который хранит параметры в словаре

class A:
    def __init__(self):
        self.parameters = {
            'self.param1': None
            'self.param2': None
        }

Таким образом, если кто-то хочет что-либо изменить, он может вместо этого написать self.parameters['param1'] = .... Я реализовал это изменение (в ветке разработки), и оно работает. Проблема в том, что другие люди используют этот код, и если я сделаю это изменение, это сломает их код (это простое исправление, но все же).

Я хотел знать, есть ли способ сделать это таким что если кто-то напишет старым способом (например, parameters.param1 = ...), он все равно будет работать, но напечатает сообщение DEPRECATED, когда он это сделает, таким образом я могу сделать окно перехода, в котором люди go со старого способа на новый . Единственный способ, который я придумал, - это если я изменю имя атрибута, я могу сохранить старый код и добавить log.warning, но я не хочу менять имя атрибута, поэтому, если кто-то может придумать способ для этого было бы здорово :)

1 Ответ

1 голос
/ 06 мая 2020

Вы можете определить make Params для реализации протокола сопоставления, а затем выдавать предупреждения об устаревании при доступе к атрибутам.

class Params:
    def __init__(self):
        ...  # As before

    def __setitem__(self, key, value):
        # This check is optional, to prevent creating new attributes
        if not hasattr(self, key):
            raise ValueError(f"No such parameter {key}")
        setattr(self, key, value)

    __getitem__ = getattr

    def __setattr__(self, attr, value):
        warnings.warn("Don't set attributes directly", DeprecationWarning)
        super().__setattr__(attr, value)

    def __getattribute__(self, attr):
        warnings.warn("Don't access attributes directly", DeprecationWarning)
        super().__getattribute__(self, attr)

Теперь ваша следующая версия будет поддерживать оба метода, но доступ к атрибуту вызовет предупреждение. В версии после вы можете избавиться от класса Params.

class A:
    def __init__(self):
        self.parameters = {
            'param1': None
            'param2': None
        }
...