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_italicejecuta 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_italicprimero 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_bolddecoró el resultado delmake_italicdecorador, que decoró lahellofunción.La
@decoratorsintaxis es realmente azúcar sintáctica; el seguimiento:se ejecuta realmente como:
reemplazando el
decorated_functionobjeto 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ó unalambdaque llama a la funciónmake_boldenvuelta, 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 innersería la versión de función 'regular'; no es una gran diferencia.make_italicdecorador se ejecuta antes que elmake_bolddecorador , porquemake_italices el más cercano aldef. Sin embargo, olvido que el orden de ejecución del código decorado : elmake_bolddecorado (es decir, lambda en negrita) se ejecuta primero, seguido por el lambdamake_italicdecorado (es decir, lambda en cursiva).