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()
Salida: "<b><i>hello world</i></b>"
Entiendo aproximadamente sobre decoradores y cómo funciona con uno de ellos en la mayoría de los ejemplos.
En este ejemplo, hay 2. De la salida, parece que se @make_italic
ejecuta primero, luego @make_bold
.
¿Significa esto que para las funciones decoradas, primero ejecutará la función y luego se moverá hacia la parte superior para otros decoradores? Como @make_italic
primero entonces @make_bold
, en lugar de lo contrario.
Entonces, ¿esto significa que es diferente de la norma del enfoque de arriba hacia abajo en la mayoría de los lenguajes de programación? ¿Solo para este caso de decorador? ¿O me equivoco?
python
decorator
python-decorators
Novato
fuente
fuente
a(b(x))
es de arriba hacia abajo (si imaginas que se divide en 3 líneas)Respuestas:
Los decoradores envuelven la función que están decorando. Así
make_bold
decoró el resultado delmake_italic
decorador, que decoró lahello
función.La
@decorator
sintaxis es realmente azúcar sintáctica; el seguimiento:se ejecuta realmente como:
reemplazando el
decorated_function
objeto original con lo que seadecorator()
devuelto.Los decoradores de apilamiento repiten ese proceso hacia afuera .
Entonces tu muestra:
se puede ampliar a:
Cuando llamas
hello()
ahora, realmente estás llamando al objeto devuelto pormake_bold()
.make_bold()
devolvió unalambda
que llama a la funciónmake_bold
envuelta, que es el valor de retorno demake_italic()
, que también es una lambda que llama al originalhello()
. Al expandir todas estas llamadas, obtienes:por lo que la salida se convierte en:
fuente
@make_bold #make_bold = make_bold(hello)
@make_italic #make_italic = make_italic (hello)
? No estoy seguro de si basándome en esto, envolverá el primer resultado. O para este caso de 2 envoltorios, ¿el IDE usarámake_bold(make_italic(hello))
como mencionaste en lugar de lo que compartí?make_bold()
envuelve la salida demake_italic()
, que se usó para envolverhello
, por lo que el equivalente demake_bold(make_italic(hello))
.def inner: return "<b>" + fn() + "</b>"
, entoncesreturn inner
sería la versión de función 'regular'; no es una gran diferencia.make_italic
decorador se ejecuta antes que elmake_bold
decorador , porquemake_italic
es el más cercano aldef
. Sin embargo, olvido que el orden de ejecución del código decorado : elmake_bold
decorado (es decir, lambda en negrita) se ejecuta primero, seguido por el lambdamake_italic
decorado (es decir, lambda en cursiva).