Saltar al contenido principal

Métodos Python Dunder: Comandos especiales que merece la pena conocer

Aprende cómo los métodos de doble guión bajo de Python permiten que tus objetos personalizados funcionen de forma natural con las operaciones incorporadas, desde la impresión hasta la aritmética. Descubre cómo estos métodos mágicos simplifican el diseño de las clases y desbloquean potentes comportamientos.
Actualizado 11 abr 2025  · 8 min de lectura

¿Te has preguntado alguna vez cómo hace Python para que tus clases personalizadas funcionen a la perfección con las funciones incorporadas? Es gracias a esos ingeniosos métodos "dunder", abreviatura de métodos de doble guión bajo.

Imagina que estás creando una clase para números complejos y quieres utilizar el operador + de forma natural. En lugar de escribir código adicional para gestionar la suma, defines un método __add__, y Python se encarga del resto.

Estos métodos mágicos, como __init__ para la creación de objetos y __str__ para la representación de cadenas, son invocados automáticamente por Python, por lo que no tienes que llamarlos directamente. Evitan conflictos de nombres con tus métodos habituales y potencian funciones como la sobrecarga de operadores y el comportamiento personalizado.

Ya sea instanciando objetos, realizando operaciones aritméticas o simplemente imprimiendo un objeto, los métodos dunder trabajan silenciosamente en segundo plano para que tu código sea más elegante y eficiente. Si eres nuevo en Python y quieres ponerte al día sobre algunas de las ideas principales, sigue nuestro curso Introducción a Python para tener una buena base.

¿Qué son los métodos Dunder en Python?

Como empecé a mencionar, los métodos dunder de Python son métodos únicos, o "mágicos", que forman la columna vertebral del modelo de datos de Python al permitir que tus clases personalizadas se integren con las operaciones incorporadas de Python. Estos operadores incluyen cosas como imprimir, comparar y realizar operaciones aritméticas.

Cuando defines métodos como __init__ para inicializar objetos, __repr__ y __str__ para la representación de objetos, o incluso __del__ para la limpieza, básicamente le estás diciendo a Python cómo manejar las operaciones estándar de tus objetos. El intérprete llama automáticamente a estos métodos cuando se realiza la operación correspondiente. Esta automatización integrada crea un puente entre las funciones nativas de Python y las clases definidas por el usuario.

Más adelante, veremos ejemplos de clases que utilizan estos métodos y de clases que no los utilizan, para que puedas ver cómo funciona todo esto.

Categorías de métodos Dunder

Exploremos las principales categorías de métodos de dunder y veamos cómo potencian tu código.

1. Inicialización y construcción

Los métodos Dunder como __new__, __init__ y __del__ controlan cómo se crean, inicializan y, finalmente, destruyen los objetos.

  • __new__ vs. __init__: __new__ se encarga de crear una nueva instancia, mientras que __init__ la inicializa. Esta separación es importante cuando trabajas con tipos inmutables, en los que podrías sustituir __new__ por otra cosa.

  • __del__: Este método actúa como destructor, permitiendo la limpieza cuando un objeto está a punto de ser recogido como basura.

Incluso puedes personalizar __new__ en clases inmutables para aplicar reglas de creación específicas.

2. Métodos numéricos y aritméticos

Los métodos Dunder como __add__, __sub__, __mul__, y sus variantes in-place permiten que tus objetos admitan operaciones aritméticas. Esto se conoce como sobrecarga de operadores. Al definir estos métodos, puedes habilitar un comportamiento aritmético natural para tus objetos personalizados.

Por ejemplo, sobrecarga __add__ en una clase Vector para sumar los elementos correspondientes de dos vectores. Esto es especialmente útil cuando se diseñan clases que modelan conceptos matemáticos o instrumentos financieros.

3. Métodos de comparación e igualdad

Métodos como __eq__, __lt__, y __gt__ determinan cómo se comparan los objetos. Estos métodos te permiten definir qué significa que dos objetos sean iguales o cómo deben ordenarse.

Un ejemplo típico es comparar las áreas de dos formas: puedes modificar __lt__ para que devuelva true si el área de una forma es menor que la de la otra. Esto puede ser útil en colecciones o algoritmos de ordenación.

4. Métodos de representación de cadenas

Los métodos __str__ y __repr__ controlan cómo se muestran tus objetos como cadenas.

  • __repr__ debe proporcionar una representación amigable para el desarrollador que pueda utilizarse para recrear el objeto.

  • __str__ se centra en una pantalla fácil de usar.

5. Métodos contenedor e iterable

Para que tus objetos se comporten como secuencias o contenedores, puedes implementar métodos como __len__, __getitem__, y __iter__. Esto permite operaciones como la indexación, la iteración y las pruebas de pertenencia.

Por ejemplo, si diseñas una pila o lista personalizada, implementar estos métodos te permite utilizar funciones incorporadas como len().

6. Llamabilidad y programación funcional

Con el método __call__, las instancias de tu clase pueden invocarse como si fueran funciones. Esto es especialmente útil para crear objetos de función con estado que puedan almacenar en caché los resultados o mantener el estado interno a través de las llamadas. Piensa en ello como si convirtieras tu objeto en un mini-motor de cálculo al que puedes llamar repetidamente con diferentes parámetros.

7. Responsables de contexto

Implementar los métodos __enter__ y __exit__ permite utilizar tus objetos con la declaración para la gestión de recursos. Esto es crucial para gestionar recursos como manejadores de archivos o conexiones de red, asegurándote de que se configuran y limpian correctamente.

Un escenario del mundo real es utilizar un gestor de contexto personalizado para abrir y cerrar conexiones a bases de datos de forma segura.

8. Acceso a atributos y descriptores

Métodos como __getattr__, __setattr__ y __delattr__ te permiten controlar cómo se accede a los atributos y cómo se modifican. El protocolo descriptor perfecciona esto al permitir que los objetos gestionen el acceso a los atributos de forma dinámica.

Por ejemplo, un descriptor podría validar o transformar valores de atributos, asegurándose de que cumplen criterios específicos antes de ser establecidos.

Métodos Dunder Avanzados y Varios  

Aunque los métodos básicos de dunder cubren la mayoría de los casos de uso, Python incluye métodos avanzados y especializados para tareas como la programación asíncrona, la metaprogramación y el comportamiento específico de las bibliotecas. Por ejemplo:  

  • Métodos asíncronos: Métodos como __aiter__ y __anext__ permiten la iteración asíncrona, mientras que __await__ admite objetos aguardables.  

  • Ganchos de metaprogramación: Métodos como __prepare__ y __set_name__ permiten crear clases dinámicas y nombrar atributos.  

  • Métodos específicos de la biblioteca: Bibliotecas como NumPy o Pandas suelen definir métodos de dunder personalizados (por ejemplo, __array__ para la integración de NumPy).

Estos métodos avanzados suelen utilizarse para tareas especializadas, de modo que la mayoría de los desarrolladores no los necesitarán a diario. Sin embargo, muestran la flexibilidad y profundidad de Python. Recomiendo explorar la documentación oficial del modelo de datos de Python para obtener una lista completa. Este recurso proporciona detalles exhaustivos sobre todos los métodos de blanqueo y su uso previsto.

Todos los métodos Dunder en Python

Python proporciona más de 100 métodos de dunder, cada uno diseñado para controlar diferentes aspectos del comportamiento de los objetos. Aunque hemos explorado las categorías clave en este artículo, aquí tienes un resumen de alto nivel que te servirá de referencia rápida:

  • Métodos aritméticos: Métodos como __add__, __sub__, __mul__, y __truediv__ permiten que tus objetos admitan operadores (+, -, *, /).

  • Métodos de comparación: Métodos como __eq__, __lt__, y __gt__ definen cómo se comparan los objetos en cuanto a igualdad u orden.

  • Gestión de atributos: Con métodos como __getattr__, __setattr__, y __delattr__, puedes controlar el acceso a atributos e implementar comportamientos dinámicos.

  • Inicialización y construcción: __new__, __init__, y __del__ gestionan la creación, inicialización y limpieza de objetos, respectivamente.

  • Representación en cadena: Métodos como __str__ y __repr__ determinan cómo se representan los objetos en forma de cadenas, lo que facilita la salida.

  • Iteración y comportamiento del contenedor: Implementa __iter__ y __next__ para que tus objetos sean iterables y otros métodos para soportar la indexación y la recuperación de longitudes.

  • Llamabilidad: __call__ Permite llamar a una instancia como si fuera una función, lo que permite un estilo de programación funcional con comportamiento de estado.

  • Gestión del contexto: Con __enter__ y __exit__, se pueden utilizar objetos con sentencias para gestionar adecuadamente los recursos.

  • Ganchos de metaprogramación: Métodos como __init_subclass__ proporcionan formas de personalizar dinámicamente la creación y el comportamiento de las clases.

Consulta la documentación oficial del Modelo de Datos de Python para obtener una lista completa y detallada de estos métodos dunder y sus funcionalidades. Este completo recurso te ayudará a liberar toda la potencia del modelo de objetos de Python y a elaborar un código más elegante y eficiente.

Ejemplos reales y casos de uso

Exploremos cómo los métodos dunder pueden potenciar los escenarios del mundo real a través de algunos ejemplos.

Sobrecarga de operadores

Imagina que tienes una clase numérica o de cadena personalizada. Implementando métodos de dunder como __add__ o __mul__, permites que tus objetos trabajen de forma natural con operadores aritméticos. Puedes sumar, restar o multiplicar instancias igual que harías con los tipos incorporados, haciendo que tus clases personalizadas se integren perfectamente con las operaciones aritméticas de Python.

class Vector:
   def __init__(self, x, y):
        self.x = x
        self.y = y
   def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
   def __str__(self):
        return f"Vector({self.x}, {self.y})"

# Usage
v1 = Vector(1, 2)
v2 = Vector(3, 4)

result = v1 + v2
print(result)  # Output: Vector(4, 6)

Almacenamiento en caché con capacidad de llamada

¿Alguna vez has querido evitar repetir cálculos costosos? Implementando el método __call__, puedes hacer que un objeto se comporte como una función que almacena en caché sus resultados. Esto te permite almacenar el resultado de un cálculo pesado y devolverlo rápidamente en llamadas posteriores, optimizando el rendimiento y ahorrando un valioso tiempo de procesamiento.

class CachedComputation:
   def __init__(self):
        self.cache = {}
   def __call__(self, x):
        if x not in self.cache:
            self.cache[x] = self._expensive_computation(x)
        return self.cache[x]
   def _expensive_computation(self, x):
        # Imagine a complex calculation here
        return x ** 2

# Usage
compute = CachedComputation()

print(compute(5))  # Computes and caches: Output: 25
print(compute(5))  # Retrieves from cache: Output: 25

Gestores de contexto personalizados

Construir un gestor de contextos utilizando los métodos __enter__ y __exit__ te permite automatizar la gestión de recursos. Por ejemplo, puedes diseñar un gestor de contexto personalizado que se encargue de las operaciones con archivos: abrir un archivo al entrar en un bloque y asegurarse de que se cierra al salir. Esto simplifica tu código y evita errores comunes como la fuga de recursos.

class FileHandler:
   def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
   def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file
   def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

# Usage
with FileHandler("example.txt", "r") as file:
    content = file.read()
    print(content)

Iterables y contenedores personalizados

Para que tus contenedores personalizados funcionen con los bucles y comprensiones de Python, implementa el protocolo de iteración definiendo métodos como __iter__ y __next__. Tanto si estás construyendo una pila personalizada, una cola o cualquier otro contenedor, estos métodos permiten recorrer tus objetos en bucle como si fueran una lista normal, mejorando la flexibilidad y utilidad de tus clases.

class Stack:
   def __init__(self):
        self.items = []
   def push(self, item):
	self.items.append(item)
   def pop(self):
        return self.items.pop()
   def __iter__(self):
        self.index = 0
        return self
   def __next__(self):
        if self.index >= len(self.items):
            raise StopIteration
        item = self.items[self.index]
        self.index += 1
        return item

# Usage
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)

for item in stack:
    print(item)  # Output: 1, 2, 3

Para saber más sobre los iterables personalizados y el comportamiento de los contenedores, consulta el Tutorial de Listas de Python y el Tutorial y Ejemplos de Funciones y Métodos de Listas de Python.

Buenas prácticas con los métodos Dunder

Cuándo y cómo anular los métodos dunder es esencial. Aquí tienes algunas pautas a tener en cuenta:

Cuándo anular

Sólo anula los métodos dunder si necesitas personalizar el comportamiento. Por ejemplo, si quieres que tus objetos admitan comprobaciones aritméticas o de igualdad de una forma específica, entonces merece la pena implementar métodos como __add__ o __eq__.

Coherencia

Si anulas un método, como __eq__ para comprobar la igualdad, actualiza en consecuencia los métodos relacionados, como __hash__. Esta coherencia garantiza que tus objetos se comporten correctamente en colecciones como conjuntos o diccionarios.

Evita el uso excesivo

Resiste a la tentación de crear nuevos nombres de truño fuera del modelo de datos estándar de Python. Si te ciñes al conjunto integrado de métodos de dunder, tu código se mantendrá claro y evitarás comportamientos inesperados.

Consideraciones sobre el rendimiento

Ten en cuenta que sobrescribir métodos dunder forma excesiva, especialmente en partes de tu código que se ejecutan con frecuencia, puede afectar al rendimiento. Busca implementaciones eficientes para evitar cualquier ralentización en las operaciones de alta frecuencia.

Conclusión y otros recursos

Los métodos Dunder permiten que tus clases Python interactúen a la perfección con las funciones integradas del lenguaje, haciendo que tu código sea más limpio e intuitivo. Permiten que tus objetos gestionen todo, desde la aritmética y las comparaciones hasta la gestión de atributos personalizados, sin que tú tengas que hacer un esfuerzo adicional. Deberías experimentar con estos métodos en tus proyectos y ver cómo pueden simplificar operaciones complejas.

Para obtener información más detallada, consulta la documentación oficial sobre el modelo de datos de Python. También te resultarán útiles nuestros recursos del DataCamp:


Oluseye Jeremiah's photo
Author
Oluseye Jeremiah
LinkedIn

Redactor técnico especializado en IA, ML y ciencia de datos, que hace que las ideas complejas sean claras y accesibles.

Temas

Aprende Python con DataCamp

Certificación disponible

Curso

Python intermedio

4 hr
1.2M
Mejora tus conocimientos de ciencia de datos creando visualizaciones con Matplotlib y manipulando DataFrames con pandas.
Ver detallesRight Arrow
Comienza el curso
Ver másRight Arrow
Relacionado

blog

Cómo aprender Python desde cero en 2024: Guía del experto

Descubre cómo aprender Python, sus aplicaciones y la demanda de conocimientos de Python. Comienza hoy tu andadura en Python ​con nuestra guía completa.
Matt Crabtree's photo

Matt Crabtree

15 min

Tutorial

Función del guión bajo(_) en el tutorial de Python

En este tutorial, vas a aprender sobre los usos del guión bajo(_) en python.
Hafeezul Kareem Shaik's photo

Hafeezul Kareem Shaik

8 min

Tutorial

Tutorial sobre cómo ejecutar scripts en Python

Aprenda cómo puede ejecutar un script Python desde la línea de comandos, y también cómo puede proporcionar argumentos de línea de comandos a su script.
Aditya Sharma's photo

Aditya Sharma

10 min

Tutorial

Programación orientada a objetos (POO) en Python: Tutorial

Aborda los fundamentos de la Programación Orientada a Objetos (POO) en Python: explora las clases, los objetos, los métodos de instancia, los atributos y ¡mucho más!
Théo Vanderheyden's photo

Théo Vanderheyden

12 min

Tutorial

Tutorial de funciones de Python

Un tutorial sobre funciones en Python que cubre cómo escribir funciones, cómo invocarlas y mucho más.
Karlijn Willems's photo

Karlijn Willems

14 min

Tutorial

Tutorial Python Docstrings : Ejemplos y Formato de Cadenas Doc Pydoc, Numpy, Sphinx

Aprende sobre las Docstrings de Python. Encuentra diferentes ejemplos y tipos de formato de docstrings para Sphinx, Numpy y Pydoc.
Aditya Sharma's photo

Aditya Sharma

15 min

Ver másVer más