Например, есть функция, которая принимает аргументы и простой декоратор. Попробуем применить декоратор к функции с параметрами:
def sample_decorator(func): def wrapper(): dash = '-'*15 print(dash) func() print(dash) return wrapper @sample_decorator def say(name): print('Привет {name}.') >>> say('Андрей') # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: wrapper() takes 0 positional arguments but 1 was given
При выполнении этого кода возникает ошибка. Проблема в том, что внутренняя функция wrapper()
не принимает никаких аргументов, а мы пытались ей передать один аргумент name
. Эту проблему можно исправить, позволив wrapper()
принять один аргумент, но тогда она не будет работать для функций, которые не принимают аргументов или принимают больше одного аргумента.
Решение заключается в использовании *args
и **kwargs
во внутренней функции wrapper()
декоратора. Тогда она будет принимать произвольное число позиционных и ключевых аргументов. Перепишем декоратор с использованием *args
и **kwargs
в функции обертке wrapper()
, а так же будем передавать произвольное число позиционных и ключевых аргументов функции func()
, которую декоратор получает в качестве аргумента:
def sample_decorator(func): def wrapper(*args, **kwargs): dash = '-'*15 print(dash) func(*args, **kwargs) print(dash) return wrapper @sample_decorator def say(name): print('Привет {name}.') >>> say('Андрей') # --------------- # Привет Андрей. # ---------------
В примере выше, вложенная функция wrapper()
принимает любое количество аргументов и передает их в декорируемую функцию func()
. Теперь декоратор @sample_decorator
будет работать как для функций, которые вообще не принимают аргументы, так и для функций которые принимают произвольное количество аргументов.