Apariencia
📙 Clase 17 — Métodos dunder (__str__, __eq__…)
Fase 3 · Programación Orientada a Objetos ⬅️ Volver al índice de clases
🎯 Qué aprendí
- Los métodos dunder (double underscore) conectan tu clase con la sintaxis de Python.
__str__/__repr__(imprimir),__len__(medir),__eq__(comparar).- Ya conocía uno:
__init__. Son la razón de quelen(),==yprint()"sepan" qué hacer.
📖 PARTE TEÓRICA
🪄 1. ¿Qué son?
Los dunder (__asi__) son métodos con nombre especial que Python llama por ti cuando usas su sintaxis:
| Tú escribes | Python llama | Para |
|---|---|---|
Contacto("Ana","1") | __init__ | construir (¡ya lo usas!) |
print(obj) / str(obj) | __str__ | texto "bonito" para humanos |
obj en consola / repr(obj) | __repr__ | texto técnico para programadores |
len(obj) | __len__ | medir |
a == b | __eq__ | comparar por contenido |
a < b | __lt__ | ordenar (sorted lo usa) |
for x in obj | __iter__ | recorrer |
obj[i] | __getitem__ | indexar |
🖨️ 2. __str__ y __repr__: imprimir con sentido
Sin ellos, imprimir un objeto muestra basura técnica:
python
class SinStr:
pass
print(SinStr()) # <__main__.SinStr object at 0x104f81a30> 😕Con ellos:
python
class Playlist:
def __init__(self, nombre, canciones):
self.nombre = nombre
self.canciones = canciones
def __str__(self): # para el USUARIO (print, f-strings)
return f"Playlist '{self.nombre}' con {len(self.canciones)} canciones"
def __repr__(self): # para el PROGRAMADOR (debug, consola)
return f"Playlist({self.nombre!r}, {self.canciones!r})"
pl = Playlist("Focus", ["a", "b"])
print(pl) # Playlist 'Focus' con 2 canciones
print(repr(pl)) # Playlist('Focus', ['a', 'b'])🧪 Tip de entrevista: "¿
__str__vs__repr__?" →__str__es legible para el usuario final;__repr__es inequívoco para debug (idealmente, código que recrea el objeto). Si solo defines__repr__,
📏 3. __len__ y __eq__
python
class Playlist:
# …(lo de arriba)…
def __len__(self):
return len(self.canciones)
def __eq__(self, otra):
return self.canciones == otra.canciones
pl = Playlist("Focus", ["a", "b"])
print(len(pl)) # 2 ← len() ya funciona
print(pl == Playlist("Otra", ["a", "b"])) # True ← compara CONTENIDO⚠️ Sin
__eq__,a == bcompara identidad (¿son el mismo objeto en memoria?), no contenido. Por eso dosContacto("Ana","1")idénticos danFalsehasta que defines__eq__.
🖥️ EN TU APP DE ESCRITORIO
Los dunder hacen que tus modelos se integren natural con la GUI y con el debug:
python
class Tarea:
def __init__(self, texto):
self.texto = texto
self.hecha = False
def __str__(self): # lo que muestra la GUI
return f"{'✅' if self.hecha else '⬜'} {self.texto}"
def __eq__(self, otra): # para detectar duplicados
return self.texto.lower() == otra.texto.lower()
# En la GUI, pintar es directo — el f-string llama a __str__ solo:
for tarea in tareas:
ctk.CTkLabel(lista, text=f"{tarea}").pack()
# Y evitar duplicados se lee como español:
nueva = Tarea(entry.get())
if nueva in tareas: # 'in' usa __eq__ por detrás
label_error.configure(text="Esa tarea ya existe")💡
nueva in tareasfuncionando "gratis" gracias a__eq__— el operadorinde la Clase 01 compara con==elemento a elemento.
🗄️ CON BASE DE DATOS (caso de uso)
__repr__ vale oro al depurar lo que sale de la BD:
python
filas = [Contacto(n, t) for n, t in con.execute("SELECT nombre, tel FROM contactos")]
print(filas)
# Sin __repr__: [<Contacto object at 0x…>, <Contacto object at 0x…>] 😖
# Con __repr__: [Contacto('Ana', '999-111'), Contacto('Luis', '988-222')] 😍🏋️ EJERCICIOS CON SOLUCIÓN
Ejercicio 1 — Imprimible
Dale a Producto(nombre, precio) un __str__ → "Teclado — S/120".
Ver solución
python
class Producto:
def __init__(self, nombre, precio):
self.nombre = nombre
self.precio = precio
def __str__(self):
return f"{self.nombre} — S/{self.precio}"
print(Producto("Teclado", 120)) # Teclado — S/120Ejercicio 2 — Comparable
Haz que dos Producto sean iguales si comparten nombre (ignorando mayúsculas).
Ver solución
python
class Producto:
def __init__(self, nombre, precio):
self.nombre = nombre
self.precio = precio
def __eq__(self, otro):
return self.nombre.lower() == otro.nombre.lower()
print(Producto("Mouse", 45) == Producto("MOUSE", 60)) # True (mismo nombre)Ejercicio 3 — Medible
Crea Curso(nombre, alumnos) (lista) con __len__, y comprueba len(curso).
Ver solución
python
class Curso:
def __init__(self, nombre, alumnos):
self.nombre = nombre
self.alumnos = alumnos
def __len__(self):
return len(self.alumnos)
c = Curso("Python", ["Ana", "Luis", "Marta"])
print(len(c)) # 3❓ Preguntas y respuestas (autoevaluación)
1. ¿Quién llama a los métodos dunder?
Python, automáticamente, cuando usas su sintaxis (
==,len,in,[]…).
2. ¿Qué compara == entre dos objetos sin __eq__?
Identidad (si son el mismo objeto en memoria), no contenido.
3. ¿Cuál es para el usuario y cuál para el programador: __str__/__repr__?
__str__→ usuario (print);__repr__→ programador (debug/consola).__repr__como respaldo si no hay__str__.
4. ¿Qué dunder hace funcionar if nueva in tareas?
__eq__—incompara con==contra cada elemento.
📎 Apuntes relacionados
- El primer dunder que usaste → Clase 13 ·
__init__ insobre listas → Clase 01
➡️ Siguiente
Clase 18 · Tu app como clase — el gran refactor: juntar TODA la Fase 3.