python - patron - Orden de ejecución del decorador
patron decorator python (1)
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>"
En términos generales, entiendo sobre decoradores y cómo funciona con uno de ellos en la mayoría de los ejemplos.
En este ejemplo, hay 2 de él.
De la salida, parece que
@make_italic
ejecuta primero, luego
@make_bold
.
¿Esto significa que para las funciones decoradas, primero ejecutará la función y luego se moverá hacia la parte superior para otros decoradores?
Al igual que
@make_italic
primero y luego
@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 las lang de programación? ¿Solo para este caso de decorador? ¿O estoy equivocado?
Los decoradores
envuelven
la función que están decorando.
Así que
make_bold
decoró el resultado del decorador
make_italic
, que decoró la función
hello
.
La sintaxis de
@decorator
es realmente solo azúcar sintáctica;
el seguimiento:
@decorator
def decorated_function():
# ...
se ejecuta realmente como:
def decorated_function():
# ...
decorated_function = decorator(decorated_function)
reemplazando el objeto
decorated_function
original con cualquier
decorator()
devuelto.
Apilar decoradores repite ese proceso hacia afuera .
Entonces su muestra:
@make_bold
@make_italic
def hello():
return "hello world"
se puede ampliar a:
def hello():
return "hello world"
hello = make_bold(make_italic(hello))
Cuando llamas a
hello()
ahora, estás llamando al objeto devuelto por
make_bold()
, realmente.
make_bold()
devolvió una
lambda
que llama a la función
make_bold
, que es el valor de retorno de
make_italic()
, que también es una lambda que llama al
hello()
original
hello()
.
Expandiendo todas estas llamadas que obtienes:
hello() = lambda : "<b>" + fn() + "</b>" # where fn() ->
lambda : "<i>" + fn() + "</i>" # where fn() ->
return "hello world"
entonces la salida se convierte en:
"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"