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 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 siente más Python. Este artículo le introducirá a 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 Python que definen cómo se comportan los objetos 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, son comúnmente llamados métodos dunder, como en double underscore. Un método dunder común que puede que ya haya encontrado es el método __init__()
que se utiliza para definir constructores de clases.
Normalmente, los métodos dunder no están pensados para 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. Utilizándolos, usted especifica el comportamiento de sus tipos de datos personalizados cuando se utilizan con operaciones comunes incorporadas. Estas operaciones incluyen:
🟢 Operaciones aritméticas
🟢 Operaciones de comparación
🟢 Operaciones de ciclo de vida
🟢 Operaciones de representación
La siguiente sección tratará sobre cómo implementar métodos mágicos que definan cómo se comporta la aplicación cuando se utiliza en todas las categorías anteriores.
Cómo definir métodos mágicos
Como se ha mencionado anteriormente, los métodos mágicos especifican el comportamiento de los objetos. Como tales, se definen como parte de la clase del objeto. Dado que forman parte de la clase del objeto, toman como primer argumento self
, que es una referencia al propio objeto.
Pueden tomar argumentos adicionales dependiendo de cómo vayan a ser llamados por el intérprete. También se definen claramente con dos guiones bajos antes y después de sus nombres.
Implementación
Gran parte de lo que hemos discutido hasta ahora parece teórico y abstracto. En esta sección, implementaremos una simple clase Rectángulo.
Esta clase tendrá propiedades de longitud y anchura. Utilizando el método __init__, podrá especificar estas propiedades en la instanciación. Además, podrá comparar diferentes rectángulos para ver si es igual, menor o mayor que otro utilizando 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 ejecución Python. Puede utilizar uno local, o puede utilizar el compilador de Python en línea de Geekflare.
Creación de la clase rectángulo
En primer lugar, empecemos por definir la clase Rectángulo.
clase Rectángulo:
pass
Creación del método constructor
A continuación, vamos a crear nuestro primer método mágico, el método constructor de la clase. Este método tomará la altura y la anchura y las almacenará como atributos en la instancia de la clase.
clase Rectángulo:
def __init__(self, altura, anchura):
self.altura = altura
self.anchura = anchura
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 Rectángulo
como argumento. Este método también será llamado cuando llamemos a funciones que esperan un argumento de cadena, como la función print
.
clase Rectángulo:
def __init__(self, altura, anchura):
self.altura = altura
self.anchura = anchura
def __str__(self):
return f'Rectángulo({altura.self}, {anchura.self})'
El método __str__(
) debe devolver una cadena que usted quiera que represente al objeto. En este caso, estamos devolviendo una cadena del formato Rectángulo(<altura>, <anchura>)
donde altura y anchura 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 denomina sobrecarga de operadores. Para crearlos, utilizaremos 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.
clase Rectángulo:
def __init__(self, altura, anchura):
self.altura = altura
self.anchura = anchura
def __str__(self):
return f'Rectángulo({altura.self}, {anchura.self})'
def __eq__(self, otro):
""" Comprobación de igualdad """
return altura.auto * anchura.auto == altura.otro * anchura.otro
def __lt__(self, otro):
""" Comprobación de si el rectángulo es menor que el otro """
return altura.auto * anchura.auto < altura.otro * anchura.otro
def __gt__(self, otro):
""" Comprobar si el rectángulo es mayor que el otro """
return altura.propia * anchura.propia > altura.ajena * anchura.ajena
Como puede ver, estos métodos reciben dos parámetros. El primero es el rectángulo actual, y el segundo es el otro valor con el que se está comparando. Este valor puede ser otra instancia de Rectángulo o cualquier otro valor. La lógica de la comparación y las condiciones bajo las cuales la comparación devolverá verdadero dependen completamente de usted.
Métodos mágicos comunes
En la siguiente sección, discutiremos los métodos mágicos comunes que encontrará y utilizará.
#1. Operaciones aritméticas
Los métodos mágicos aritméticos son llamados cuando una instancia de su clase se sitúa a la izquierda de un signo aritmético. El método será llamado con dos argumentos, siendo el primero una referencia a la instancia. El segundo es el objeto situado a la derecha del signo. Los métodos y los signos son los siguientes:
Nombre | Método | Signo | Descripción |
Suma | __add__ | Implementa la suma. | |
Resta | __sub__ | – | Implementa la sustracción. |
Multiplicación | __mul__ | * | Implementa la multiplicación |
División | __div__ | / | Implementa la división. |
División de suelo | __floordiv__ | // | Implementa la división del suelo. |
#2. Operaciones de comparación
Al igual que los métodos aritméticos mágicos, estos métodos son llamados cuando una instancia de la clase para la que están definidos se sitúa a la izquierda del operador de comparación. También, como los métodos aritméticos mágicos, son llamados con dos parámetros; el primero es una referencia a la instancia del objeto. El segundo es una referencia al valor situado a la derecha del signo.
Nombre | Método | Signo | Descripción |
Menor que | __lt__ | < | Implementa la comparación menor que |
Mayor que | __gt__ | > | Implementa la comparación mayor que |
Igual a | __eq__ | == | Implementa la comparación igual a |
Menor o igual que | __le__ | >= | Implementa la comparación menor o igual que |
Mayor o igual que | __ge__ | <= | Implementa la comparación mayor o igual que |
#3. Operaciones del ciclo de vida
Estos métodos serán llamados en respuesta a los diferentes métodos del ciclo de vida de un objeto, como ser instanciado o borrado. El constructor, __init__
entra dentro de esta categoría. Los métodos comunes de esta categoría se enumeran en la siguiente tabla:
Nombre | Método | Descripción |
Constructor | __init__ | Este método es llamado cada vez que se elimina un objeto de la clase para la que está definido. Puede utilizarse para realizar acciones de limpieza, como cerrar cualquier archivo que hubiera abierto. |
Borrado | __del__ | Este método es llamado cada vez que se borra un objeto de la clase para la que está definido. Puede utilizarse para realizar acciones de limpieza como cerrar cualquier archivo que haya abierto. |
Nuevo | __nuevo__ | El método __new__ es llamado en primer lugar cuando se instancia 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 cubre en detalle aquí. |
#4. Operaciones de representación
Nombre | Método | Descripción |
Str | __str__ | Devuelve una representación en forma de cadena legible por humanos del objeto. Se llama a este método cuando se llama a la función str( ), pasando una instancia de la clase como argumento. También se llama cuando se pasa la instancia a las funciones print() y format() . Su finalidad es proporcionar una cadena comprensible para el usuario final de la aplicación. |
Repr | __repr__ | Devuelve una representación en forma de cadena del objeto que utiliza el desarrollador. Lo ideal es que la cadena devuelta sea rica en información, de forma que se pueda construir una instancia idéntica del objeto a partir sólo 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 que tenga en cuenta lo siguiente cuando los utilice.
- Utilícelos 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 sólo los esenciales.
- Asegúrese de que comprende las implicaciones para el rendimiento de métodos como __setatrr__ y __getattr__ antes de utilizarlos.
- Documente el comportamiento de sus métodos mágicos para que otros desarrolladores sepan exactamente lo que hacen. Así les resultará más fácil utilizarlos y depurarlos cuando sea necesario.
Palabras finales
En este artículo, he introducido los métodos mágicos como una forma de crear clases que se pueden utilizar con operaciones incorporadas. También hablé de cómo se definen y repasé un ejemplo de una clase que implementa métodos mágicos. A continuación, mencioné los diferentes métodos que probablemente va a utilizar y necesitar antes de compartir algunas de las mejores prácticas a tener en cuenta.
A continuación, es posible que desee aprender a implementar la clase Contador en Python.