Вложение декораторов в Python
Python для начинающих » Общие вопросы decorators python урок, Python декораторы, вложение декораторов Python
Иногда одного декоратора бывает недостаточно. Для поддержки многоступенчатых расширений синтаксис декораторов позволяет добавлять несколько уровней обертывающей логики к декорируемой функции или методу. При использовании такой возможности каждый декоратор должен указываться в отдельной строке. Синтаксическая конструкция следующего вида:
@AAA
@BBB
@CCC
def function(...):
...
равноценна следующей:
def f(...):
...
f = AAA(BBB(CCC(f)))
Здесь оригинальная функция передается трем различным декораторам, а получившийся в результате вызываемый объект присваивается оригинальному имени. Каждый декоратор обрабатывает результат, возвращаемый предыдущим декоратором, который может быть оригинальной функцией или объектом-оберткой. Если все декораторы возвращают обертки, то при вызове функции по оригинальному имени будет выполнена логика всех трех обертывающих объектов, расширяя возможности функции тремя различными способами.
Последний декоратор в списке будет задействован первым и окажется самым глубоко вложенным.
Так же как и в случае декорирования функций, применение нескольких декораторов классов приведет к вызову нескольких вложенных функций и, возможно, к созданию нескольких уровней обертывающей логики вокруг операции создания экземпляров. Например, следующий фрагмент:
@firsdecorator
@seconddecorator
class CDC:
...
MyInstance = CDC()
эквивалентен следующему:
class CDC:
...
C = firstdecorator(seconddecorator(CDC))
XX = C()
Как и прежде, каждый декоратор может возвращать оригинальный класс или объект обертку. Если оба декоратора в примере возвращают обертки, то позднее, когда будет предпринята попытка создать экземпляр оригинального класса CDC, вызов будет направлен обертывающим объектам, созданным обоими декораторами, firstdecorator и seconddecorator, которые могут преследовать совершенно разные цели.
Например, следующие декораторы просто возвращают декорируемую функцию, не выполняя никаких дополнительных действий:
def fn1(arg): return arg
def fn2(arg): return arg
def fn3(arg): return arg
@fn1
@fn2
@fn3
def myfunc(): # myfunc = fn1(fn2(fn3(myfunc)))
print('Hello')
myfunc() # Выдает "Hello"
При применении аналогичных ничего не делающих декораторов к классам результат будет похожим.
Однако когда декораторы добавляют обертывающие объекты функций, они могут расширять возможности оригинальных функций - в следующем примере происходит объединение результатов в ходе выполнения уровней обертывающей логики декораторов от внутренней к внешней:
def fn1(arg): return lambda: 'XX' + arg()
def fn2(arg): return lambda: 'YY' + arg()
def fn3(arg): return lambda: 'ZZ' + arg()
@fn1
@fn2
@fn3
def myfunc(): # myfunc = fn1(fn2(fn3(myfunc)))
return 'Python'
print(myfunc()) # Выведет "XXYYZZPython"
Для реализации обертывающей логики мы использовали здесь lambda-функции (каждая из них сохраняет обертываемую функцию в области видимости объемлющей функции). На практике обертки могут быть реализованы в виде функций, вызываемых классов и других объектов. В случае удачной конструкции декораторов возможность их вложения друг в друга дает нам возможность составлять из них самые разнообразные комбинации.
- Модуль threading на примерах
- Игровой автомат Butterfly Staxx - играй выгодно в Вулкан казино
- Игровой автомат Chimney Sweep - играй везде, скачать Вулкан казино на cazinoclubvulkan.co
- Игровой автомат Warlords: Crystals of Power - за незабываемыми победами в Вулкан казино
- Работа со списками Python
- Как создавать сайты в Python?
- Игровой автомат Viking Gods Thor and Loki - в мобильное казино Вулкан 24 поймай удачу