Introducción
Contenido de la lección.
Objetivos de aprendizaje
- Objetivo 1
- Objetivo 2
- Objetivo 3
Objetivos de Aprendizaje
Al finalizar este tema, serás capaz de:
- Comprender el concepto y propósito de los métodos especiales en Python
- Implementar métodos especiales fundamentales como __init__, __str__ y __repr__
- Aplicar sobrecarga de operadores para crear clases más intuitivas y funcionales
- Desarrollar clases que se integren naturalmente con las funciones built-in de Python
📚 Conceptos Fundamentales de Métodos Especiales
Los métodos especiales son la base del modelo de datos de Python y permiten que las clases personalizadas se comporten como tipos de datos nativos. El método __init__ es el constructor que se ejecuta al crear una instancia. __str__ define la representación de cadena para usuarios finales, mientras que __repr__ proporciona una representación técnica para desarrolladores. Estos métodos se invocan automáticamente cuando se utilizan operadores o funciones específicas. La convención de dobles guiones bajos indica que estos métodos tienen un significado especial para el intérprete de Python. Es importante distinguir entre __str__ (legible para humanos) y __repr__ (no ambigua para desarrolladores). Una buena práctica es que __repr__ devuelva una expresión que pueda recrear el objeto.
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
def __str__(self):
return f'{self.nombre}, {self.edad} años'
def __repr__(self):
return f'Persona("{self.nombre}", {self.edad})'
# Crear instancia y probar métodos
p = Persona('Ana', 25)
print(str(p))
print(repr(p))
print(p) # Usa __str__ por defecto
Ana, 25 años Persona("Ana", 25) Ana, 25 años
🎯 Sobrecarga de Operadores Aritméticos
La sobrecarga de operadores permite que nuestras clases respondan a operadores como +, -, *, / de manera personalizada. Los métodos especiales correspondientes son __add__, __sub__, __mul__, __div__, etc. También existen versiones de asignación como __iadd__ para +=. Es importante implementar operadores de manera consistente e intuitiva. Los operadores deben devolver nuevas instancias cuando sea apropiado, manteniendo la inmutabilidad cuando sea deseable. La sobrecarga de operadores hace que el código sea más legible y natural, permitiendo que los objetos personalizados se comporten como tipos numéricos nativos.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'Vector({self.x}, {self.y})'
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
# Usar operadores sobrecargados
v1 = Vector(2, 3)
v2 = Vector(1, 4)
print(v1 + v2)
print(v1 - v2)
print(v1 * 3)
Vector(3, 7) Vector(1, -1) Vector(6, 9)
💡 Operadores de Comparación y Métodos de Contenedor
Los operadores de comparación (__eq__, __lt__, __le__, __gt__, __ge__, __ne__) permiten que los objetos se comparen usando ==, <, <=, >, >=, !=. Los métodos de contenedor como __len__, __getitem__, __setitem__, __contains__ hacen que los objetos se comporten como secuencias o diccionarios. __len__ se invoca con len(), __getitem__ con [], __contains__ con 'in'. Estos métodos son fundamentales para crear clases que se integren con las funciones built-in de Python y los protocolos del lenguaje. Una implementación correcta permite que nuestros objetos se usen con sorted(), max(), min(), y otras funciones estándar.
class MiLista:
def __init__(self):
self.items = []
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.items[index]
def __setitem__(self, index, value):
self.items[index] = value
def __contains__(self, item):
return item in self.items
def agregar(self, item):
self.items.append(item)
# Usar métodos de contenedor
mi_lista = MiLista()
mi_lista.agregar('Python')
mi_lista.agregar('Java')
print(len(mi_lista))
print(mi_lista[0])
print('Python' in mi_lista)
2 Python True
🔧 Métodos Especiales Avanzados y Context Managers
Los métodos especiales avanzados incluyen __call__ (hace que el objeto sea callable), __enter__ y __exit__ (para context managers con 'with'), __iter__ y __next__ (para iteradores), y __hash__ (para objetos hasheable). __call__ permite que una instancia se comporte como una función. Los context managers con __enter__ y __exit__ manejan recursos de manera segura. Los iteradores permiten usar objetos en bucles for. __hash__ es necesario para usar objetos como claves de diccionario. Estos métodos proporcionan funcionalidad avanzada y hacen que las clases sean más versátiles y pythónicas.
class Contador:
def __init__(self, inicio=0, fin=5):
self.inicio = inicio
self.fin = fin
self.actual = inicio
def __call__(self):
return f'Contador de {self.inicio} a {self.fin}'
def __iter__(self):
self.actual = self.inicio
return self
def __next__(self):
if self.actual < self.fin:
self.actual += 1
return self.actual - 1
raise StopIteration
# Usar objeto callable e iterable
c = Contador(1, 4)
print(c()) # Llamar como función
for num in c: # Iterar sobre el objeto
print(f'Número: {num}')
Contador de 1 a 4 Número: 1 Número: 2 Número: 3
Ejercicios Prácticos
Clase Fracción con Operadores Aritméticos
INTERMEDIODescripción:
Crea una clase Fraccion que represente fracciones matemáticas. Implementa __init__, __str__, __repr__, y los operadores +, -, *, / para realizar operaciones entre fracciones. Incluye un método para simplificar fracciones.
Lista Personalizada con Métodos de Comparación
INTERMEDIODescripción:
Desarrolla una clase ListaOrdenada que mantenga sus elementos siempre ordenados. Implementa métodos de contenedor (__len__, __getitem__, __contains__) y comparación (__eq__, __lt__) para comparar listas por su longitud.
Context Manager para Archivos
AVANZADODescripción:
Crea una clase MiArchivo que actúe como context manager para manejo de archivos. Implementa __enter__ y __exit__ para abrir y cerrar archivos automáticamente. Añade métodos para lectura y escritura.
Clase Dinero con Múltiples Operadores
AVANZADODescripción:
Desarrolla una clase Dinero que maneje cantidades monetarias con diferentes monedas. Implementa operadores aritméticos, comparación, y métodos especiales para conversión de tipos. Incluye validación de monedas compatibles.
Resumen y Próximos Pasos
Los métodos especiales son fundamentales para crear clases pythónicas que se integren naturalmente con el ecosistema del lenguaje. Hemos explorado desde los métodos básicos como __init__, __str__ y __repr__, hasta conceptos avanzados como context managers e iteradores. La sobrecarga de operadores permite que nuestros objetos se comporten de manera intuitiva, mientras que los métodos de contenedor hacen que las clases personalizadas funcionen con las funciones built-in de Python. El siguiente tema explorará herencia y polimorfismo, conceptos que se complementan perfectamente con los métodos especiales para crear jerarquías de clases robustas y flexibles.