from functools import wraps import time ''' Такой декоратор работать не будет ''' ''' def html_tag(func, name_tag='h1'): def inner(*args, **kwargs): result = func(*args, **kwargs) return f'<{name_tag}>{result}' return inner ''' ''' def decorator_factory(a, b): print('Запуск функции создания декоратора') def decorator(fn): print('Запуск декоратора') def wrapper(*args, **kwargs): print('Запуск функции wrapper') print('Переданные аргументы: ', a, b) return fn(*args, **kwargs) return wrapper return decorator ''' ''' Можно раскрыть следующей записью decorator = decorator_factory() # получаем декоратор из decorator_factory original_func = decorator(original_func) # декорируем Или есть еще вариант original_func = decorator_facotry()(original_func) ''' ''' @decorator_factory(10, 20) # Обратите внимание на оператор вызова def original_func(): print('Запуск оригинальной функции') ''' ''' Рабочий вариант декоратора ''' def html_tag(name_tag='h1'): def decorator(func): @wraps(func) def inner(*args, **kwargs): result = func(*args, **kwargs) return f'<{name_tag}>{result}' return inner return decorator @html_tag(name_tag='table') @html_tag('td') @html_tag() @html_tag('p') def say_hello_to(name, surname): return f'Hello {name} {surname}' def cached_with_expiry(expiry_time): def decorator(original_function): cache = {} # словарь для хранения кеша def wrapper(*args, **kwargs): key = (*args, *kwargs.items()) if key in cache: cached_value, cached_timestamp = cache[key] if time.time() - cached_timestamp < expiry_time: return f'[CACHED] - {cached_value}' result = original_function(*args, **kwargs) cache[key] = (result, time.time()) return result return wrapper return decorator @cached_with_expiry(expiry_time=5) def get_product(x, y): return x*y def multiply_result_by(n): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): result = func(*args, **kwargs) return n*result return wrapper return decorator def limit_query(n): def decorator(func): limit = n @wraps(func) def wrapper(*args, **kwargs): nonlocal limit if limit == 0: print(f'Лимит вызовов закончен, все {n} попытки израсходованы') return None else: limit -= 1 return func(*args, **kwargs) return wrapper return decorator @limit_query(3) def add(a: int, b: int): return a + b def monkey_patching(arg='Monkey', kwarg='patching'): def decorator(func): @wraps(func) def wrapper(*_args, **_kwargs): patched_args = (arg, )*len(_args) patched_kwargs = {key:kwarg for key, _ in _kwargs.items()} return func(*patched_args, **patched_kwargs) return wrapper return decorator @monkey_patching(kwarg='Duper') def print_args_kwargs(*args, **kwargs): for i, value in enumerate(args): print(i, value) for k, v in sorted(kwargs.items()): print(f'{k} = {v}') def pass_arguments(*args_, **kwargs_): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): print(args_, kwargs_) return func(*args, **kwargs) return wrapper return decorator @pass_arguments(s='Когда', w='-', r='нибудь!') def concatenate(**kwargs): result = "" for arg in kwargs.values(): result += str(arg) return result def main(): print(concatenate(a="Я", b="Выучу", c="Этот", d="Питон", e="!")) # print_args_kwargs(1, 2, 3, 4, b=300, w=40, t=50, a=100) ''' print(get_product(23, 5)) # Вычисляем в первый раз print(get_product(23, 5)) # Во второй раз срабатывает кеш time.sleep(5) print(get_product(23, 5)) # Кеш просрочился, поэтому вновь вычисляется значение ''' # original_func() # print(say_hello_to('Vasiliy', 'Ytkin')) if __name__ == '__main__': main()