¿Qué son los métodos mágicos en Python y cómo usarlos?

Una de las características menos conocidas pero valiosas de Python es la capacidad de implementar métodos mágicos en los objetos. Usando métodos mágicos, podemos escribir un código más limpio que sea intuitivo y fácil de entender.

Con métodos mágicos, podemos crear interfaces para interactuar con objetos de una manera que se sienta más Pythonic. Este artículo le presentará los métodos mágicos, discutirá las mejores prácticas para crearlos y explorará los métodos mágicos comunes que encontrará.

¿Qué son los métodos mágicos?

Los métodos mágicos son métodos de Python que definen cómo se comportan los objetos de Python cuando se realizan operaciones comunes sobre ellos. Estos métodos se definen claramente con guiones bajos dobles antes y después del nombre del método.

Como resultado, comúnmente se les llama métodos dunder, como en doble guión bajo. Un método común de dunder que quizás ya haya encontrado es el método __init__() que se usa para definir constructores de clases.

Por lo general, los métodos de dunder no están destinados a ser llamados directamente en su código; más bien, serán llamados por el intérprete mientras se ejecuta el programa.

¿Por qué son útiles los métodos mágicos?

Los métodos mágicos son un concepto útil en la Programación Orientada a Objetos en Python. Usándolos, usted especifica el comportamiento de sus tipos de datos personalizados cuando se usan con operaciones integradas comunes. Estas operaciones incluyen:

🟢 Operaciones aritméticas

🟢 Operaciones de comparación

🟢 Operaciones de ciclo de vida

🟢 Operaciones de representación

La siguiente sección discutirá cómo implementar métodos mágicos que definen cómo se comporta la aplicación cuando se usa en todas las categorías anteriores.

Cómo definir métodos mágicos

Como se mencionó anteriormente, los métodos mágicos especifican el comportamiento de los objetos. Como tales, se definen como parte de la clase del objeto. Debido a que son parte de la clase de objeto, toman como primer argumento self, que es una referencia al objeto mismo.

Pueden tomar argumentos adicionales dependiendo de cómo los llamará el intérprete. También se definen claramente con dos guiones bajos antes y después de sus nombres.

Implementación

Mucho de lo que hemos discutido hasta ahora parece teórico y abstracto. En esta sección, implementaremos una clase Rectángulo simple.

Esta clase tendrá propiedades de largo y ancho. Con el método __init__, puede especificar estas propiedades en la creación de instancias. Además, podrás comparar diferentes rectángulos para ver si es igual, menor o mayor que otro usando los operadores ==, < y >. Por último, el rectángulo debe ser capaz de proporcionar una representación de cadena significativa.

Configuración del entorno de codificación

Para seguir este tutorial, necesitará un entorno de tiempo de ejecución de Python. Puede usar uno local o puede usar el compilador de Python kirukiru.es en línea.

Crear la clase Rectángulo

Primero, comencemos definiendo la clase Rectangle.

class Rectangle:
    pass

Creando el Método Constructor

A continuación, creemos nuestro primer método mágico, el método constructor de clases. Este método tomará la altura y el ancho y los almacenará como atributos en la instancia de la clase.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

Creación de un método mágico para la representación de cadenas

A continuación, queremos crear un método que permita a nuestra clase generar una cadena legible por humanos para representar el objeto. Este método será llamado siempre que llamemos a la función str() pasando una instancia de la clase Rectangle como argumento. Este método también se llamará cuando llame a funciones que esperan un argumento de cadena, como la función de impresión.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def __str__(self):
        return f'Rectangle({self.height}, {self.width})'

El método __str__() debería devolver una cadena que le gustaría representar el objeto. En este caso, devolvemos una cadena con el formato Rectangle(, ) donde alto y ancho son las dimensiones almacenadas del rectángulo.

Creación de métodos mágicos para operaciones de comparación

A continuación, queremos crear operadores de comparación para las operaciones igual a, menor que y mayor que. Esto se llama sobrecarga de operadores. Para crearlos, usamos los métodos mágicos __eq__, __lt__ y __gt__ respectivamente. Estos métodos devolverán un valor booleano después de comparar las áreas de los rectángulos.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def __str__(self):
        return f'Rectangle({self.height}, {self.width})'

    def __eq__(self, other):
        """ Checking for equality """
        return self.height * self.width == other.height * other.width

    def __lt__(self, other):
        """ Checking if the rectangle is less than the other one """
        return self.height * self.width < other.height * other.width

    def __gt__(self, other):
        """ Checking if the rectage is greater than the other one """
        return self.height * self.width > other.height * other.width

Como puede ver, estos métodos toman dos parámetros. El primero es el rectángulo actual y el segundo es el otro valor con el que se compara. Este valor puede ser otra instancia de Rectangle o cualquier otro valor. La lógica de cómo la comparación y las condiciones bajo las cuales la comparación será verdadera dependen completamente de usted.

Métodos mágicos comunes

En la próxima sección, discutiremos los métodos mágicos comunes que encontrará y utilizará.

#1. Operaciones aritmeticas

Los métodos mágicos aritméticos se llaman cuando una instancia de su clase se coloca en el lado izquierdo de un signo aritmético. El método será llamado con dos argumentos, siendo el primero una referencia a la instancia. El segundo valor es el objeto a la derecha del signo. Los métodos y signos son los siguientes:

NameMethodSignDescriptionAddition__add__+Implementa la adición. Subtraction__sub__–Implementa la resta.Multiplication__mul__*Implementa la multiplicaciónDivision__div__/Implementa la división.División del piso__floordiv__//Implementa la división del piso.

#2. Operaciones de comparación

Al igual que los métodos mágicos aritméticos, estos métodos se llaman cuando una instancia de la clase para la que están definidos se coloca a la izquierda del operador de comparación. Además, al igual que los métodos mágicos aritméticos, se les llama con dos parámetros; el primero es una referencia a la instancia del objeto. El segundo es una referencia al valor en el lado derecho del signo.

NameMethodSignDescriptionLess than__lt__Implementa la comparación mayor queIgual a__eq__==Implementa la comparación igual aMenor que o igual a__le__>=Implementa la comparación menor o igual aMayor que o igual a__ge__<=Implementa la comparación mayor o igual a comparación

#3. Operaciones del ciclo de vida

Estos métodos se llamarán en respuesta a los diferentes métodos del ciclo de vida de un objeto, como instancias o eliminación. El constructor, __init__ entra en esta categoría. Los métodos comunes en esta categoría se enumeran en la siguiente tabla:

NameMethodDescriptionConstructor__init__Este método se llama cada vez que se elimina un objeto de la clase para la que está definido. Se puede usar para realizar acciones de limpieza, como cerrar cualquier archivo que haya abierto. Deletion__del__Este método se llama cada vez que se elimina un objeto de la clase para la que está definido. Se puede usar para realizar acciones de limpieza, como cerrar cualquier archivo que haya abierto. Nuevo__nuevo__El método __nuevo__ se llama primero cuando se crea una instancia de un objeto de la clase especificada. Este método se llama antes que el constructor y toma la clase así como cualquier argumento adicional. Devuelve una instancia de la clase. En su mayor parte, no es demasiado útil, pero se trata en detalle aquí.

#4. Operaciones de Representación

NameMethodDescriptionStr__str__Devuelve una representación de cadena legible por humanos del objeto. Este método se llama cuando llamas a la función str(), pasando una instancia de la clase como argumento. También se llama cuando pasa la instancia a las funciones print() y format(). Su objetivo es proporcionar una cadena que sea comprensible para el usuario final de la aplicación. Repr__repr__Devuelve una representación de cadena del objeto que utiliza el desarrollador. Idealmente, la cadena devuelta debe ser rica en información, de modo que pueda construir una instancia idéntica del objeto solo a partir de la cadena.

Mejores prácticas para crear métodos mágicos

Los métodos mágicos son increíbles y simplificarán su código. Sin embargo, es importante tener en cuenta lo siguiente cuando los use.

  • Úselos con moderación: implementar demasiados métodos mágicos en sus clases hace que su código sea difícil de entender. Limítese a implementar solo los esenciales.
  • Asegúrese de comprender las implicaciones de rendimiento de métodos como __setatrr__ y __getattr__ antes de usarlos.
  • Documente el comportamiento de sus métodos mágicos para que otros desarrolladores puedan saber exactamente lo que hacen. Esto les facilita su uso y depuración cuando sea necesario.

Ultimas palabras

En este artículo, presenté métodos mágicos como una forma de crear clases que se pueden usar con operaciones integradas. También discutí cómo se definen y analicé un ejemplo de una clase que implementó métodos mágicos. A continuación, mencioné los diferentes métodos que probablemente usará y necesitará antes de compartir algunas mejores prácticas para tener en cuenta.

A continuación, es posible que desee aprender a implementar la clase Counter en Python.