9. Métodos mágicos¶
Los métodos mágicos son métodos especiales que empiezan y terminan con dos guiones bajos (__).
También se les llama métodos dunder, por la abreviatura de «double underscore». Los métodos
mágicos no se deben invocar directamente por el usuario, sino que se ejecutan internamente por
la clase en ciertas situaciones. Por ejemplo, cuando se suma dos números usando el operador +,
internamente se llama al método __add__()
.
Las clases integradas en Python definen muchos métodos mágicos. Puedes usar la función dir()
para ver el número de métodos mágicos heredados por una clase.
Por ejemplo, el siguiente código muestra todos los atributos y métodos definidos en la clase
int
:
>>> print(dir(int))
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__',
'__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__',
'__format__', '__ge__', '__getattribute__', '__getnewargs__', '__getstate__', '__gt__',
'__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__',
'__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__',
'__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__',
'__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__',
'__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__',
'__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__',
'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag',
'numerator', 'real', 'to_bytes']
>>>
Como puedes ver, la clase int incluye varios métodos mágicos rodeados por dos guiones bajos.
Por ejemplo, el método __add__
:
9.1. Método __add__¶
Es un método mágico que se usa cuando se suman dos números usando el operador +. Considera el siguiente ejemplo:
>>> num = 10
>>> res = num.__add__(5)
>>> print(res)
15
>>>
Como puedes ver, cuando haces num + 10
, el operador + llama al método
__add__(10)
. También puedes llamar a num.__add__(5)
directamente, lo que dará el mismo resultado.
Sin embargo, como se mencionó antes, los métodos mágicos no se deben llamar directamente, sino internamente,
a través de otros métodos o acciones.
Los métodos mágicos se usan con más frecuencia para definir comportamientos sobrecargados de los operadores predefinidos en Python. Por ejemplo, los operadores aritméticos por defecto operan sobre operandos numéricos.
Esto significa que los objetos numéricos deben usarse junto con operadores como +, -, *, /, etc. El operador + también está definido como un operador de concatenación en las clases cadenas de caracteres, listas y tuplas. Podemos decir que el operador + está sobrecargado.
Para hacer que el comportamiento sobrecargado esté disponible en tu propia clase personalizada, el método mágico
correspondiente debe ser redefinido. Por ejemplo, para usar el operador + con objetos de
una clase definida por el usuario, debe incluir el método __add__()
. Veamos cómo implementar y usar algunos de
los métodos mágicos más importantes.
9.2. Método __new__¶
Es un método mágico que se usa para crear una nueva instancia de una clase. Se llama antes
que el método __init__()
, que es el constructor de la clase. El método __new__()
recibe la clase como
primer argumento y devuelve una instancia de esa clase. Por ejemplo, el siguiente código crea una clase
Singleton
que solo permite una instancia de sí misma.
>>> class Singleton:
... """Clase Singleton"""
... # Variable de clase que almacena la instancia única
... _instance = None
... def __new__(cls, *args, **kwargs):
... """Método mágico para crear una nueva instancia"""
... # Si no hay una instancia previa, se crea una nueva
... if cls._instance is None:
... cls._instance = super().__new__(cls, *args, **kwargs)
... # Se devuelve la instancia única
... return cls._instance
... def show_id(self):
... """Método para mostrar el id de la instancia"""
... print(f"El id de esta instancia es {id(self)}")
...
>>>
Crear dos objetos de la clase Singleton
:
>>> obj1 = Singleton()
>>> obj2 = Singleton()
>>>
Mostrar el id de cada objeto:
>>> obj1.show_id()
El id de esta instancia es 140376583855472
>>> obj2.show_id()
El id de esta instancia es 140376583855472
>>>
Como puedes ver, los dos objetos tienen el mismo id, lo que significa que son la misma instancia.
9.3. Método __init__¶
Es el método mágico que se usa para inicializar una nueva instancia de una clase. Se
llama después del método __new__()
, y recibe la instancia como primer argumento, seguido de los
argumentos que se pasan al constructor de la clase. El método __init__()
no devuelve ningún valor,
sino que asigna los atributos a la instancia. Por ejemplo, el siguiente código crea una clase Persona
que tiene un nombre y una edad como atributos.
>>> class Persona:
... def __init__(self, nombre, edad):
... """Método mágico para inicializar una nueva instancia"""
... self.nombre = nombre
... self.edad = edad
... def mostrar(self):
... """Método para mostrar los datos de la persona"""
... print(f"Esta persona se llama {self.nombre} y tiene {self.edad} años")
...
>>>
Crear una persona con el nombre «Ana» y la edad 25:
>>> p = Persona("Ana", 25)
Mostrar los datos de la persona:
>>> p.mostrar()
Esta persona se llama Ana y tiene 25 años
Como puedes ver, el método __init__()
asigna los valores de nombre y edad a la instancia p
, que luego
se pueden usar en el método mostrar()
.
9.4. Método __str__¶
Es un método mágico que se usa para devolver una representación en forma de cadena de una instancia de una
clase. Se llama cuando se usa la función str()
o cuando se imprime la instancia. El método __str__()
debe
devolver una cadena que describa el objeto de forma amigable para el usuario. Por ejemplo, el siguiente
código modifica la clase Persona
para incluir el método __str__()
.
>>> class Persona:
... def __init__(self, nombre, edad):
... """Método mágico para inicializar una nueva instancia"""
... self.nombre = nombre
... self.edad = edad
... def __str__(self):
... """Método mágico para devolver una representación en forma de cadena"""
... return f"Persona(nombre={self.nombre}, edad={self.edad})"
...
>>>
Crear una persona con el nombre «Ana» y la edad 25:
>>> p = Persona("Ana", 25)
>>>
Imprimir la persona usando el método __str__()
:
>>> print(p)
Persona(nombre=Ana, edad=25)
>>>
Como puedes ver, el método __str__()
devuelve una cadena que muestra los atributos de la persona.
9.5. Método __repr__¶
Es un método mágico que se usa para devolver una representación en forma de cadena de una instancia de
una clase. Se llama cuando se usa la función repr()
o cuando se muestra la instancia en el intérprete
interactivo. El método __repr__()
debe devolver una cadena que sea una expresión válida de Python que
pueda recrear el objeto. Por ejemplo, el siguiente código modifica la clase Persona para incluir el
método __repr__()
.
>>> class Persona:
... def __init__(self, nombre, edad):
... """Método mágico para inicializar una nueva instancia"""
... self.nombre = nombre
... self.edad = edad
... def __repr__(self):
... """Método mágico para devolver una representación en forma de cadena"""
... return f"Persona('{self.nombre}', {self.edad})"
...
>>>
Crear una persona con el nombre «Ana» y la edad 25
>>> p = Persona("Ana", 25)
>>>
Mostrar la persona usando el método __repr__()
>>> print(repr(p))
Persona('Ana', 25)
>>>
Como puedes ver, el método __repr__()
devuelve una cadena que es una expresión de Python que puede crear
una nueva instancia de la persona con los mismos atributos.
Ver también
Consulte la sección de lecturas suplementarias del entrenamiento para ampliar su conocimiento en esta temática.
¿Cómo puedo ayudar?
¡Mi soporte está aquí para ayudar!
Mi horario de oficina es de lunes a sábado, de 9 AM a 5 PM. GMT-4 - Caracas, Venezuela.
La hora aquí es actualmente 7:35 PM GMT-4.
Mi objetivo es responder a todos los mensajes dentro de un día hábil.