Рубрики
Без рубрики

Декоратор класса Python – часть II – с аргументами конфигурации

показать протокол о декораторе на основе классов python с аргументами конфигурации

Автор оригинала: Dobri Stoilov.

Здесь мы продолжаем раскрывать протокол о декораторе на основе классов и о том, как он реализован в python3. Вы можете проверить и предыдущую статью: как конструктор классов строит без аргументов В большинстве случаев мы хотели бы передать аргументы нашему декоратору, чтобы настроить вещи, необходимые для упаковки. Сходство с теми, у кого нет аргументов, заключается в том, что нам снова нужны оба метода init и call … но теперь логика немного изменилась, давайте проверим:

class MyClassDecorator:
    def __init__(self, *a, **kw):
        print('__init__',a ,kw)

    def __call__(self, *a, **kw):
        print('__call__',a, kw)


@MyClassDecorator(1,2,3,"decorator configuration")
def my_function(*args, **kwargs):
    print('call my_function', args, kwargs)
    return 3

Когда мы запускаем скрипт, теперь легко понять, что и куда переместилось…

Python 3.7.0 (default, Jan 29 2019, 14:54:06)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.2.0 -- An enhanced Interactive Python. Type '?' for help.
__init__ (1, 2, 3, 'decorator configuration') {}
__call__ (,) {}

Вы видите, как аргументы не передаются одинаково, теперь сначала в нем просто берет то, что необходимо для настройки, в вашу функциональность обертывания, а исходная функция передается в вызов

Мы можем использовать ту же методологию, что и в предыдущей статье, и поставить псевдо-цели, которые будут эмулировать что-то общее о шаблоне декоратора, и это не сильно отличается от предыдущего случая, это просто улучшается с нашей пользовательской (и может быть по умолчанию) конфигурацией и параметризацией, всегда делая вещи гибкими и повторно полезными.

class MyClassDecorator:
    def __init__(self, *a, **kw):
        self.conf_args = a
        self.conf_kw = kw
        # self.func  = None
       
    def __call__(self, func):
        # self.func = func
        def wrapper(*args, **kwargs):
            print('preprocessing')
            print('preprocessing configuration', self.conf_args, self.conf_kw)
            if args:
                if isinstance(args[0], int):
                    a = list(args)
                    a[0] += 5
                    args = tuple(a)
                    print('preprocess OK', args) 
            r = func(*args, **kwargs)
            print('postprocessing', r)
            r += 7
            return r
        return wrapper
        

@MyClassDecorator(1001,a='some configuration')
def my_function(*args, **kwargs):
    print('call my_function', args, kwargs)
    return 3

и попробуйте это в оболочке

In [1]: my_function(1,2,3, a="OK")
preprocessing
preprocessing configuration (1001,) {'a': 'some configuration'}
preprocess OK (6, 2, 3)
call my_function (6, 2, 3) {'a': 'OK'}
postprocessing 3
Out[1]: 10

In [2]:

@Круто ?! – Вы видите, как интерпретатор python анализирует вашу часть магии