Logotipo de Zephyrnet

8 decoradores de Python integrados para escribir código elegante – KDnuggets

Fecha:

8 decoradores de Python integrados para escribir código elegante
Imagen por editor
 

Python, con su sintaxis limpia y legible, es un lenguaje de programación de alto nivel ampliamente utilizado. Python está diseñado para ser fácil de usar y enfatiza la simplicidad y el costo reducido de mantenimiento del programa. Viene con una biblioteca extensa que reduce la necesidad de que los desarrolladores escriban código desde cero y aumenta la productividad de los desarrolladores. Una característica poderosa de Python que contribuye a la elegancia del código son los decoradores.

En Python, un decorador es una función que le permite modificar el comportamiento de otra función sin cambiar su lógica central. Toma otra función como argumento y devuelve la función con funcionalidad extendida. De esta manera, puedes usar decoradores para agregar algo de lógica adicional a las funciones existentes para aumentar la reutilización con solo unas pocas líneas de código. En este artículo, exploraremos ocho decoradores de Python integrados que pueden ayudarlo a escribir código más elegante y fácil de mantener.

 

8 decoradores de Python integrados para escribir código elegante
Imagen por editor

El @atexit.register El decorador se utiliza para registrar una función que se ejecutará al finalizar el programa. Esta función se puede utilizar para realizar cualquier tarea cuando el programa está a punto de salir, ya sea por una ejecución normal o por un error inesperado.

Ejemplo:

import atexit

# Register the exit_handler function
@atexit.register
def exit_handler():
    print("Exiting the program. Cleanup tasks can be performed here.")

# Rest of the program
def main():
    print("Inside the main function.")
    # Your program logic goes here.

if __name__ == "__main__":
    main()

Salida:

Inside the main function.
Exiting the program. Cleanup tasks can be performed here.

 

En la implementación anterior, @atexit.register se menciona arriba de la definición de la función. Define el exit_handler() funcionar como una función de salida. Básicamente, significa que cada vez que el programa llega a su punto de terminación, ya sea mediante ejecución normal o debido a un error inesperado que causa una salida prematura, el exit_handler() Se invocará la función.

El @dataclasses.dataclass es un poderoso decorador que se utiliza para generar automáticamente métodos especiales comunes para clases como “__init__”, “__repr__” y otras. Le ayuda a escribir código más limpio y conciso al eliminar la necesidad de escribir métodos repetitivos para inicializar y comparar instancias de su clase. También puede ayudar a prevenir errores al garantizar que los métodos especiales comunes se implementen de manera consistente en todo su código base.

Ejemplo:

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int


point = Point(x=3, y=2)
# Printing object
print(point)

# Checking for the equality of two objects
point1 = Point(x=1, y=2)
point2 = Point(x=1, y=2)
print(point1 == point2)

Salida:

Point(x=3, y=2)
True

 

El @dataclass El decorador, aplicado encima de la definición de la clase Point, indica a Python que utilice el comportamiento predeterminado para generar métodos especiales. Esto crea automáticamente el __init__ método, que inicializa los atributos de clase, como x e y, al crear una instancia del objeto. Como resultado, se pueden construir instancias como point sin necesidad de codificación explícita. Además, el __repr__ El método, responsable de proporcionar una representación de cadena de objetos, también se ajusta automáticamente. Esto garantiza que cuando se imprime un objeto, como un punto, se obtiene una representación clara y ordenada, como se ve en el resultado: Punto(x=3, y=2). Además, la comparación de igualdad (==) entre dos instancias, punto1 y punto2, produce Verdadero. Esto es digno de mención porque, de forma predeterminada, Python verifica la igualdad según la ubicación de la memoria. Sin embargo, en el contexto de los objetos de clase de datos, la igualdad está determinada por los datos contenidos en ellos. Esto se debe a que el decorador @dataclass genera un __eq__ Método que verifica la igualdad de los datos presentes en los objetos, en lugar de verificar la misma ubicación de memoria.

El @enum.unique El decorador, que se encuentra en el módulo enum, se utiliza para garantizar que los valores de todos los miembros de una enumeración sean únicos. Esto ayuda a evitar la creación accidental de varios miembros de enumeración con el mismo valor, lo que puede generar confusión y errores. Si se encuentran valores duplicados, se ValorError es elevado.

Ejemplo:

from enum import Enum, unique

@unique
class VehicleType(Enum):
    CAR = 1
    TRUCK = 2
    MOTORCYCLE = 3
    BUS = 4

# Attempting to create an enumeration with a duplicate value will raise a ValueError
try:
    @unique
    class DuplicateVehicleType(Enum):
        CAR = 1
        TRUCK = 2
        MOTORCYCLE = 3
        # BUS and MOTORCYCLE have duplicate values
        BUS = 3
except ValueError as e:
    print(f"Error: {e}")

 

Salida:

Error: duplicate values found in : BUS -> MOTORCYCLE

 

En la implementación anterior, “BUS” y “MOTORCYCLE” tienen el mismo valor “3”. Como resultado, el @unique El decorador genera un ValueError con un mensaje que indica que se han encontrado valores duplicados. Tampoco puedes utilizar la misma clave más de una vez ni asignar el mismo valor a diferentes miembros. De esta manera, ayuda a evitar valores duplicados para varios miembros de la enumeración.

El partial decorador es una herramienta poderosa que se utiliza para crear funciones parciales. Las funciones parciales le permiten preestablecer algunos de los argumentos de la función original y generar una nueva función con esos argumentos ya completados.

Ejemplo:

from functools import partial

# Original function
def power(base, exponent):
    return base ** exponent

# Creating a partial function with the exponent fixed to 2
square = partial(power, exponent=2)

# Using the partial function
result = square(3)
print("Output:",result)

 

Salida:

 

En la implementación anterior, tenemos una función "potencia" que acepta dos argumentos "base" y "exponente" y devuelve el resultado de la base elevada a la potencia del exponente. Hemos creado una función parcial llamada "cuadrado" usando la función original en la que el exponente está preestablecido en 2. De esta manera, podemos ampliar la funcionalidad de las funciones originales usando una partial decorador.

El @singledisptach El decorador se utiliza para crear funciones genéricas. Le permite definir diferentes implementaciones de funciones con el mismo nombre pero diferentes tipos de argumentos. Es particularmente útil cuando desea que su código se comporte de manera diferente para diferentes tipos de datos.

Ejemplo:

from functools import singledispatch

# Decorator
@singledispatch
def display_info(arg):
    print(f"Generic: {arg}")

# Registering specialized implementations for different types
@display_info.register(int)
def display_int(arg):
    print(f"Received an integer: {arg}")

@display_info.register(float)
def display_float(arg):
    print(f"Received a float: {arg}")

@display_info.register(str)
def display_str(arg):
    print(f"Received a string: {arg}")

@display_info.register(list)
def display_sequence(arg):
    print(f"Received a sequence: {arg}")

# Using the generic function with different types
display_info(39)             
display_info(3.19)          
display_info("Hello World!")
display_info([2, 4, 6])     

 

Salida:

Received an integer: 39
Received a float: 3.19
Received a string: Hello World!
Received a sequence: [2, 4, 6]

 

En la implementación anterior, primero desarrollamos la función genérica display_info() usando el @singledisptach decorador y luego registró su implementación para int, float, string y list por separado. El resultado muestra el funcionamiento de display_info() para tipos de datos separados.

El @classmethod es un decorador utilizado para definir métodos de clase dentro de la clase. Los métodos de clase están vinculados a la clase y no al objeto de la clase. La principal distinción entre métodos estáticos y métodos de clase radica en su interacción con el estado de la clase. Los métodos de clase tienen acceso y pueden modificar el estado de la clase, mientras que los métodos estáticos no pueden acceder al estado de la clase y operar de forma independiente.

Ejemplo:

class Student:
    total_students = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age
        Student.total_students += 1

    @classmethod
    def increment_total_students(cls):
        cls.total_students += 1
        print(f"Class method called. Total students now: {cls.total_students}")

# Creating instances of the class
student1 = Student(name="Tom", age=20)
student2 = Student(name="Cruise", age=22)

# Calling the class method
Student.increment_total_students()  #Total students now: 3

# Accessing the class variable
print(f"Total students from student 1: {student1.total_students}")
print(f"Total students from student 2: {student2.total_students}")

 

Salida:

Class method called. Total students now: 3
Total students from student 1: 3
Total students from student 2: 3

 

En la implementación anterior, el Estudiante la clase tiene total_estudiantes como variable de clase. El @classmethod El decorador se utiliza para definir el increment_total_students() método de clase para incrementar el total_estudiantes variable. Siempre que creamos una instancia de la clase Estudiante, el número total de estudiantes se incrementa en uno. Creamos dos instancias de la clase y luego usamos el método de clase para modificar la total_estudiantes variable a 3, que también se refleja en las instancias de la clase.

El @staticmethod El decorador se utiliza para definir métodos estáticos dentro de una clase. Los métodos estáticos son los métodos que se pueden llamar sin crear una instancia de la clase. Los métodos estáticos se utilizan a menudo cuando no tienen que acceder a parámetros relacionados con objetos y están más relacionados con la clase en su conjunto.

Ejemplo:

class MathOperations:
    @staticmethod
    def add(x, y):
        return x + y

    @staticmethod
    def subtract(x, y):
        return x - y

# Using the static methods without creating an instance of the class
sum_result = MathOperations.add(5, 4)
difference_result = MathOperations.subtract(8, 3)

print("Sum:", sum_result)            
print("Difference:", difference_result)

 

Salida:

Sum: 9
Difference: 5

 

En la implementación anterior, hemos utilizado @staticmethod para definir un método estático add() para la clase “MathOperations”. Hemos agregado los dos números "4" y "5" lo que da como resultado "9" sin crear ninguna instancia de la clase. De manera similar, resta los dos números "8" y "3" para obtener "5". De esta manera se pueden generar métodos estáticos para realizar funciones de utilidad que no requieren el estado de una instancia. 

El @property El decorador se utiliza para definir los métodos getter para el atributo de clase. Los métodos getter son los métodos que devuelven el valor de un atributo. Estos métodos se utilizan para la encapsulación de datos que especifica quién puede acceder a los detalles de la clase o instancia.

Ejemplo:

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        # Getter method for the radius.
        return self._radius

    @property
    def area(self):
        # Getter method for the area.
        return 3.14 * self._radius**2

# Creating an instance of the Circle class
my_circle = Circle(radius=5)

# Accessing properties using the @property decorator
print("Radius:", my_circle.radius)          
print("Area:", my_circle.area)  

 

Salida:

Radius: 5
Area: 78.5

 

En la implementación anterior, la clase "Círculo" tiene un atributo "radio". Hemos usado @property para configurar los métodos getter para el radio y el área. Proporciona una interfaz limpia y coherente para que los usuarios de la clase accedan a estos atributos. 

Este artículo destaca algunos de los decoradores más versátiles y funcionales que puede utilizar para hacer que su código sea más flexible y legible. Estos decoradores le permiten ampliar las funcionalidades de la función original para hacerla más organizada y menos propensa a errores. Son como toques mágicos que hacen que sus programas Python se vean limpios y funcionen sin problemas.
 
 

Kanwal Mehreen es un aspirante a desarrollador de software con un gran interés en la ciencia de datos y las aplicaciones de IA en medicina. Kanwal fue seleccionado como Google Generation Scholar 2022 para la región APAC. A Kanwal le encanta compartir conocimientos técnicos escribiendo artículos sobre temas de actualidad y le apasiona mejorar la representación de las mujeres en la industria tecnológica.

punto_img

Información más reciente

punto_img