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

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

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__ (<function my_function at 0x7f16f0404ae8>,) {}

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

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

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 разбирает вашу магию 😃

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *