Класс `__init__` с декоратором, вызываемым при импорте - PullRequest
1 голос
/ 04 августа 2020

У меня есть декоратор, который помогает определять атрибуты класса, поступающие из глобального файла конфигурации. Функция выглядит так:

config_data = {
    "resourceA": {"a": "foo", "b": "bar"},
    "resourceB": {"x": "baz", "y": "boo"}
}

def autoinit(resource: str = None, data: dict = config_data, **kwargs):
    print(f'here for {resource}')
    if not kwargs:
        if resource:
            kwargs = data[resource]  # get defaults

    def wrapper(func):
        def wrapped(*args, **configs):
            kwargs.update(configs)  # update kwargs with overrides
            return func(*args, **kwargs)

        return wrapped

    return wrapper

Этот декоратор действует таким образом, что если у меня есть класс:

class ResourceA:
    @autoinit(resource="resourceA")
    def __init__(self, a, b):
        self.a = a
        self.b = b
    # other stuff

class ResourceB:
    @autoinit(resource="resourceB")
    def __init__(self, x, y):
        self.x = x
        self.y = y
    # other stuff

будет автоматически установлен из конфигурации данных.

Теперь, когда я выполняю импорт

from module.submodule import ResourceA

, я получаю:

here for resourceA
here for resourceB

Почему декоратор вызывается, когда я еще не создал экземпляр класса?

Это фиктивная версия реальной проблемы, с которой я столкнулся. Это прерывает мое тестирование, поскольку data: dict = config_data фактически загружается из файла по умолчанию. Когда я запускаю свои тесты, существует версия, в которой файл по умолчанию не существует, но я не могу ее пройти.

Есть мысли?

1 Ответ

0 голосов
/ 04 августа 2020

Можно изменить функцию декоратора как таковую:

def autoinit(resource: str = None, data: dict = config_data, **kwargs):

    def wrapper(func):

        def wrapped(*args, **configs):

            nonlocal kwargs

            if not kwargs:
                if resource:
                    kwargs = data[resource]

            kwargs.update(configs)  # update kwargs with overrides
            return func(*args, **kwargs)

        return wrapped

    return wrapper
...