Плавное вхождение в понимание - что такое Декораторы:
Функция без параметров | Функция с одним параметром | Общий случай (много параметров) |
def func_decorator(func): def wrapper(): print("--before call func-") func() print("--after call func--") return wrapper def some_func(): print("Вызов функции some_func") f = func_decorator(some_func) f() |
def func_decorator(func): def wrapper(title): print("--before call func-") func(title) print("--after call func--") return wrapper def some_func(title): print(f"title = {title}") some_func = func_decorator(some_func) some_func("Python навсегда!") |
def func_decorator(func): def wrapper(*args, **kwargs): print("--before call func-") res = func(*args, **kwargs) print("--after call func--") return res return wrapper def some_func(title, tag): print(f"title = {title}, tag = {tag}") return f"<{tag}>{title}</{tag}>" some_func = func_decorator(some_func) res = some_func("Python навсегда!", 'h1') print(res) |
import time def test_time(fn): def wrapper(*args, **kwargs): st = time.time() res = fn(*args, **kwargs) dt = time.time() - st print(f"Время работы: {dt} сек") return res return wrapper def get_nod(a, b): while a != b: if a > b: a -= b else: b -= a return a def get_fast_nod(a, b): if a < b: a, b = b, a while b: a, b = b, a % b return a get_nod = test_time(get_nod) get_fast_nod = test_time(get_fast_nod) res1 = get_nod(2, 1000000) res2 = get_fast_nod(2, 1000000) print(res1, res2) |
import time def test_time(fn): def wrapper(*args, **kwargs): st = time.time() res = fn(*args, **kwargs) dt = time.time() - st print(f"Время работы: {dt} сек") return res return wrapper @test_time def get_nod(a, b): while a != b: if a > b: a -= b else: b -= a return a @test_time def get_fast_nod(a, b): if a < b: a, b = b, a while b: a, b = b, a % b return a res1 = get_nod(2, 1000000) res2 = get_fast_nod(2, 1000000) print(res1, res2) |
Обычная запись функции: | ... превращается в запись функции обёрнутой в фикстуру: |
get_nod = test_time(get_nod) ... |
@test_time def get_nod(a, b): ... |
Декоратор (просто):
def deco(f): def wrap(*args, **kwargs): print('---- pre ----') res = f(*args, **kwargs) print('=== after ===') return res return wrap @deco def fun(a, b, c): print('fun print:', a + b + c) return 'fun return: ' + str(a + b + c) rf = fun(3, 5, 1) print(rf) |
---- pre ---- fun print: 9 === after === fun return: 9 |
Передача параметра через Декоратор:
import math def df_decorator(dx=0.0001): def func_decorator(func): def wrapper(x, *args, **kwargs): res = (func(x+dx, *args, **kwargs) - func(x, *args, **kwargs)) / dx return res wrapper.__doc__ = func.__doc__ return wrapper return func_decorator @df_decorator(dx=0.01) def sin_df(x): """Функция для вычисления производной синуса""" return math.sin(x) df = sin_df(math.pi/3) print(df) print(sin_df.__doc__)
Декоратор с параметром (попроще):
def master_deco(dx=8): def deco(f): def wrap(a, b, c, *args, **kwargs): print('---- pre ----') res = f(a, b, c + dx, *args, **kwargs) print('=== after ===') return res return wrap return deco @master_deco(2) def fun(a, b, c): print('fun print:', a + b + c) return 'fun return: ' + str(a + b + c) rf = fun(3, 5, 1) print(rf) |
---- pre ---- fun print: 11 === after === fun return: 11 |
Первый декоратор, разбираемся с написанием (Яндекс.Дзен - видео)