def make_bold(fn):
return lambda : "<b>" + fn() + "</b>"
def make_italic(fn):
return lambda : "<i>" + fn() + "</i>"
@make_bold
@make_italic
def hello():
return "hello world"
helloHTML = hello()
Выход: "<b><i>hello world</i></b>"
Я примерно понимаю декораторы и то, как они работают с одним из них, в большинстве примеров.
В этом примере их 2. Из вывода кажется, что @make_italic
сначала выполняется, затем @make_bold
.
Означает ли это, что для декорированных функций он сначала запускает функцию, а затем перемещается вверх для других декораторов? Вроде @make_italic
сначала тогда @make_bold
, а не наоборот.
Значит, это означает, что это отличается от нормального подхода сверху вниз в большинстве языков программирования? Как раз на этот случай декоратора? Или я не прав?
python
decorator
python-decorators
Новичок
источник
источник
a(b(x))
это нисходящий (если вы представите, что это разделение на 3 строки)Ответы:
Декораторы оборачивают функцию, которую они украшают. Так
make_bold
оформлен результатmake_italic
декоратора, украсившегоhello
функцию.@decorator
Синтаксис действительно просто синтаксический сахар; продолжение:@decorator def decorated_function(): # ...
действительно выполняется как:
def decorated_function(): # ... decorated_function = decorator(decorated_function)
замена исходного
decorated_function
объекта тем, что былоdecorator()
возвращено.Укладка декораторы повторы , которые обрабатывают наружу .
Итак, ваш образец:
@make_bold @make_italic def hello(): return "hello world"
можно расширить до:
def hello(): return "hello world" hello = make_bold(make_italic(hello))
Когда вы вызываете
hello()
сейчас, вы действительно вызываете объект, возвращаемыйmake_bold()
.make_bold()
вернул a,lambda
который вызываетmake_bold
обернутую функцию , которая является возвращаемым значениемmake_italic()
, которое также является лямбда, вызывающим оригиналhello()
. Расширяя все эти звонки, вы получаете:hello() = lambda : "<b>" + fn() + "</b>" # where fn() -> lambda : "<i>" + fn() + "</i>" # where fn() -> return "hello world"
поэтому вывод становится:
"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"
источник
@make_bold #make_bold = make_bold(hello)
@make_italic #make_italic = make_italic (hello)
? Я не уверен, что, основываясь на этом, он завершит первый результат. Или в этом случае с двумя оболочками среда IDE будет использовать,make_bold(make_italic(hello))
как вы упомянули, вместо того, что я поделился?make_bold()
обертывает выводmake_italic()
, который использовался для обертыванияhello
, поэтому эквивалентmake_bold(make_italic(hello))
.def inner: return "<b>" + fn() + "</b>"
, тогдаreturn inner
будет «обычная» версия функции; не такая уж большая разница.make_italic
декоратор выполняется передmake_bold
декоратором , посколькуmake_italic
он ближе всего кdef
. Однако я забываю, что порядок выполнения декорированного кода:make_bold
декорированная (то есть жирная лямбда) выполняется первой, а затемmake_italic
декорированная лямбда (то есть курсивная лямбда).