А!
https://nuancesprog.ru/p/5243
@nuancesprog #статьи #GitHub
Size: a a a
А!
4
SM
SM
SM
@
:@app.route('/')
def index():
return "Hello, World!"
@
) – всего лишь синтаксический сахар:@decorator
def foo():
...
def foo():
...
foo = decorator(foo)
def decorator(f):
return f
def decorator(f):
def inner():
print('inner')
return inner
def decorator(f):
def inner():
print('begin')
f()
print('end')
return inner
@decorator
def foo():
print('foo')
foo()
# begin foo
# foo
# end foo
SM
f
. Поэтому эти аргументы обычно обобщают, называя их *args
(все позиционные аргументы, как список), **kwargs
(все именованные аргументы, как словарь). Эти две штуки охватывают все возможные аргументы. Также у функции может быть возвращаемое значение, которое неплохо бы вернуть из inner
. Улучшим наш декоратор, добавив прозрачную передачу любых (заранее неизвестных) аргументов и возвращение результата выполнения функции:def decorator(f):
def inner(*args, **kwargs):
print('begin')
result = f(*args, **kwargs)
print('end')
return result
return inner
@decorator
def foo(x, y):
print(f'summing {x} and {y}...')
return x + y
print(foo(5, y=10))
# begin
# summing 5 and 10...
# end
# 15
и
вы
водится при вызове help
). Декоратор из прошлого примера потеряет документацию и имя функции (она станет зваться inner
):@decorator
def foo(x, y):
"""Doc string here"""
return x + y
help(foo)
# Help on function inner in module main:
# inner(*args, **kwargs)
Для того, чтобы предотвратить потерю атрибутов декорированной функции есть декоратор wraps в модуле functools. И да, это еще один декоратор, которым мы декорируем inner
в нашем декораторе. Вот теперь название и документация поступят в обертку из оригинальной функции:from functools import wraps
def decorator(f):
@wraps(f)
def inner(*args, **kwargs):
print('begin')
result = f(*args, **kwargs)
print('end')
return result
return inner
@decorator
def foo(x, y):
"""Doc string here"""
return x + y
help(foo)
# Help on function foo in module main:
# foo(x, y)
# Doc string here
Композиция декораторовfoo
и bar
декорированы в разном порядке:def bold(f):
def inner():
return '<b>' + f() + '</b>'
return inner
def italic(f):
def inner():
return '<i>' + f() + '</i>'
return inner
@bold
@italic
def foo():
return 'foo text'
@italic
@bold
def bar():
return 'bar text'
print(foo()) # <b><i>foo text</i></b>
print(bar()) # <i><b>bar text</b></i>
foo = italic(bold(foo))
bar = bold(italic(bar))
SM
@repeat(n=5)
def foo():
print('foo')
from functools import wraps
def repeat(n=5):
def _repeat(f):
@wraps(f)
def inner(*args, **kwargs):
for _ in range(n):
f(*args, **kwargs)
return inner
# не забываем ее вернуть!
return _repeat
SM
SM
A
c
A
A
c
A
o
A
A
Р