Как передать параметры в параметризованный декоратор?
День добрый.
Как передаете ЛЮБОЕ кол-во параметров в функцию через параметризованный декоратор? Вот функция
def parametrized_decoder(path_to_log = "files/log.txt"):
def decorator_logo(fun):
def wrapper(*args, **kwargs):
import pathlib
import datetime
log = {}
fmt = "%Y-%m-%d %H:%M:%S"
time_start = datetime.datetime.now().strftime(fmt)
name_fun = fun.__name__
pesponse = tuple(fun(*args, **kwargs))
...
return pesponse
return wrapper
return decorator_logo
Декорируемая
@parametrized_decoder
def yandex_request_put_foldr(path_in_root, folder_of_putting, header):
...
return
В данной версии ругается - мол подаете 1 параметр , а требуется 3
TypeError: decorator_logo() takes 1 positional argument but 3 were given
Задача - декоратор вешать на любую функцию. Но где-то есть внешние данные, гдк-то нету. Как в этом случает параметризовать декоратор...
Ответы (2 шт):
Если отвечать буквально на вопрос в заголовке — просто в скобках после имени декоратора указываете параметр, как для функции (параметризованный декоратор — это и есть функция, которая возвращает декоратор):
@parametrized_decoder("files/some_other_log.txt")
def yandex_request_put_foldr(path_in_root, folder_of_putting, header):
...
return
Это примерно аналогично такому коду:
decorator = parametrized_decoder("files/some_other_log.txt")
@decorator
def yandex_request_put_foldr(path_in_root, folder_of_putting, header):
...
return
Т.е. вызывается параметризованный декоратор с нужным параметром, он возвращает непараметризованный декоратор, и этот декоратор уже декорирует функцию.
Конкретно ваш декоратор имеет ровно параметр со значением по умолчанию, поэтому можно добавлять его без параметров, но скобки все равно должны остаться.
Параметризованный декоратор нужно добавлять со скобками, даже если явно параметры никакие не передаются.
Если добавить такой декоратор без скобок, то во внешнюю функцию параметром будет передана декорируемая функция (как если бы это был обычный декоратор, а не параметризованный), а функция decorator_logo будет использована как wrapper, и в нее будут переданы все три параметра декорируемой функции, а decorator_logo может принять только один, из-за этого ошибка:
TypeError: parametrized_decoder.<locals>.decorator_logo() takes 1 positional argument but 3 were given
Со скобками все будет работать:
def parametrized_decoder(path_to_log="files/log.txt"):
def decorator_logo(fun):
def wrapper(*args, **kwargs):
print("Hello from decorator!")
print(f"Path to log: {path_to_log}")
response = fun(*args, **kwargs)
return response
return wrapper
return decorator_logo
@parametrized_decoder() # <-- добавлены скобки
def yandex_request_put_foldr(path_in_root, folder_of_putting, header):
print("Hello from function!")
return
yandex_request_put_foldr("sdfsdf", "wewew", "erhgerh")
Вывод:
Hello from decorator!
Path to log: files/log.txt
Hello from function!
Чтобы параметризованный декоратор мог работать без скобок, нужно добавить явную проверку, что если первый параметр - функция, то вызвать decortator_logo с этой функцией и возвращать результат из parametrized_decoder:
from typing import Callable
def parametrized_decoder(path_to_log=None):
path_to_log_default = "files/log.txt"
path_to_log = path_to_log or path_to_log_default
def decorator_logo(fun):
def wrapper(*args, **kwargs):
print("Hello from decorator!")
print(f"Path to log: {path_to_log}")
response = fun(*args, **kwargs)
return response
return wrapper
if isinstance(path_to_log, Callable):
func = path_to_log
path_to_log = path_to_log_default
return decorator_logo(func)
return decorator_logo
@parametrized_decoder
def yandex_request_put_foldr(path_in_root, folder_of_putting, header):
print("Hello from function!")
return
yandex_request_put_foldr("sdfsdf", "wewew", "erhgerh")