qué patron parametros ejemplo decoradores decorador con python decorator python-decorators

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>"