Декоратор класса 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 разбирает вашу магию