Implementar múltiples decoradores en Python

Jay Shaw 10 octubre 2023
  1. Implementar un decorador: funciones como objetos de primera clase
  2. Implementar un decorador parametrizado en Python
  3. Implementar decorador usando @ en Python
  4. Implementar múltiples decoradores en Python
  5. Conclusión
Implementar múltiples decoradores en Python

Una de las características más predominantes de Python es que podemos usar decoradores para cambiar el comportamiento de funciones o clases. Podemos usar decoradores para hacer cambios en una parte del programa con códigos ya dentro del programa.

Los decoradores son líneas de código en un programa que cambian alguna parte de ese programa durante la ejecución. El proceso de provocar cambios en un programa durante la compilación se denomina metaprogramación.

En este artículo, el lector repasará los conceptos básicos de los decoradores, es decir, cómo se declara, implementa y encadena en Python.

Implementar un decorador: funciones como objetos de primera clase

Sintácticamente, podemos declarar decoradores pasando una función como un objeto iterable a otro. Esto es posible porque todo en Python es un objeto de primera clase; por lo tanto, podemos pasar cada construcción de Python como un parámetro o asignarlo a una variable.

Eso significa que todas las clases, funciones y variables declaradas se pueden pasar como objetos. Los siguientes ejemplos demuestran esto:

Código:

def func():
    def inner():
        print("Chocolate")

    return inner


taste = func()
taste()

Producción :

"C:\Users\Win 10\main.py"
Chocolate

Process finished with exit code 0

Aquí, se crea una función anidada, donde la función principal func() tiene una función interna inner(). La función inner() imprime una declaración y se devuelve a sí misma mientras está dentro de una función.

La función decoradora func() pasa sus datos a una función objeto vacía sabor. Decorándolo así.

Si esta función de objeto tuviera alguna funcionalidad, el decorador también le habría hecho cambios. En las últimas partes de este artículo, verá cómo se utilizan los decoradores para provocar cambios en una función.

En Python, podemos pasar y devolver funciones como argumentos a otras funciones. Un decorador también puede aceptar una función como argumento y devolver resultados usando esta noción.

El siguiente ejemplo muestra decoradores parametrizados. Para entenderlo más fácilmente, piense en las funciones como objetos del mundo real.

Implementar un decorador parametrizado en Python

Presentaremos un ejemplo de panadería para comprender cómo los decoradores pueden tomar otras funciones como argumentos parametrizados.

Aquí, la panadería es un método parametrizado que toma una función de objeto obj_func() como parámetro. Dentro de este método, se declara una función anidada inner(), que imprime Dough.

Después de eso, se llama a obj_func(), devolviendo la función inner(). Llamar a la función del objeto llama a la función que se está decorando.

Como puede observar de cerca, la panadería es un método parametrizado que toma el argumento obj_func(), que no es más que la función trigo(), y lo llama después de que la función inner() ejecuta la función imprimir declaración.

Código:

def inner():
    print("Dough")
    obj_func()


return inner

Esta función que debería estar decorada, es decir, trigo, tiene una declaración de print: Convertido en pan.

Código:

def wheat():
    print("Turned into bread")

Se crea una nueva función de objeto final que almacena la función decorada.

La sintaxis función_objeto = decorador(función_decorado) decora la función trigo() pasándola como objeto al método parametrizado panadería, que le implementa las propiedades de la función interior().

Código:

final = bakery(wheat)
final()

La función decorada se guarda en la función de objeto final. Cuando se compila, el programa ejecuta primero la función inner(), luego llama a obj_func(), que pasa la función de objeto wheat() e imprime su contenido.

En pocas palabras, el trigo se convierte en pan cuando se coloca dentro de una panadería, y el resultado se imprime: Convertido en pan. ¡Al igual que cómo funciona una panadería en el mundo real!

Código:

def bakery(obj_func):
    def inner():
        print("Dough")
        obj_func()

    return inner


def wheat():
    print("Turned into bread")


final = bakery(wheat)
final()

Producción :

"C:\Users\Win 10\main.py"
Dough
Turned into bread

Process finished with exit code 0

Implementar decorador usando @ en Python

Este segmento demuestra cómo se puede decorar una función utilizando la sintaxis @function_name. En este ejemplo, se utiliza un programa que tiene:

  • Una función anidada parametrizada;
  • Una función interna que verifica los valores entre las variables x e y y los intercambia si el numerador es más pequeño que el denominador;
  • Una tercera función que se decora con los valores intercambiados divide los dos números y los imprime.

La función decoradora decor_func toma como parámetro una función objeto obj1. En el interior, se crea la función interna que intercambia valores si se proporciona un número mayor en el campo del denominador.

Código:

def decor_func(obj1):
    def swap(x, y):
        pass

Como los parámetros de la función interna swap son los mismos que los parámetros de la función quot, los valores intercambiados almacenados dentro de obj1 se devuelven desde la función interna, pasando los valores modificados a la función quot antes de que el compilador los ejecute.

La sintaxis @decor_func se declara encima de la función quot en el ejemplo. Le dice al compilador que tome los parámetros de la función obj1 y los pase a la función quot.

Código:

def decor_func(obj1):
    def swap(x, y):
        if x < y:
            temp = x
            x = x + y - x
            y = y + temp - y
        return obj1(x, y)

    return swap


# Syntax to Decorate function
@decor_func
def quot(x, y):  # Displays quotient of variable x/y
    print(x / y)


quot(2, 4)

Producción :

"C:\Users\Win 10\main.py"
2.0

Process finished with exit code 0

Implementar múltiples decoradores en Python

El encadenamiento de decoradores es una técnica para apilar decoradores uno encima del otro para que la función de destino se decore repetidamente, por la cantidad de veces que se declara @function_name.

En el siguiente programa, se crean dos funciones, decor y decor1. Estas funciones son decoradores y tienen una función interna, que realiza operaciones aritméticas y devuelve el resultado.

Para encadenar decoradores, estos deben definirse juntos (uno encima del otro) arriba de la función a decorar. También se debe tener en cuenta que el compilador lee los decoradores de abajo hacia arriba.

Esto significa que el decorador colocado justo encima del nombre de la función se implementa primero, y los demás decoradores se implementan después, hacia la parte superior.

Código:

@decor  # Gets implemented second
@decor1  # Gets implemented first
def num():
    return 5

En el siguiente ejemplo, la función num() devuelve un valor a las funciones del decorador en serie. Al principio, decor1 toma el valor, lo pasa a la función de objeto func(), y devuelve el valor alterado a num().

De manera similar, este proceso se repite con la otra función de decorador. Finalmente, cuando se imprime num(), produce 50 como salida.

Código:

# code for testing decorator chaining
def decor1(func):
    def inner():
        x = func()
        return x * x

    return inner


def decor(func):
    def inner():
        x = func()
        return 2 * x

    return inner


@decor
@decor1
def num():
    return 5


print(num())

Producción :

"C:\Users\Win 10\main.py"
50

Process finished with exit code 0

Conclusión

Este artículo proporcionó una imagen clara al lector de cómo se utilizan los decoradores en un programa. El lector debe aprender cómo se pueden usar los decoradores para una función, cómo se pueden proporcionar parámetros a un decorador y cómo encadenar varios decoradores.

Artículo relacionado - Python Decorator