Volver al curso

Python Desde Cero

leccion
16 / 21
beginner
20 horas
Programacion Orientada a Objetos

Metodos Especiales: __init__, __str__ y mas

Lectura
20 min~4 min lectura

Metodos Especiales: init, str y mas

Los metodos especiales (dunder methods) son metodos que Python llama automaticamente en situaciones especificas. Son la clave para que tus clases se integren naturalmente con el lenguaje.

str y repr
class Producto:
    def __init__(self, nombre, precio, stock):
        self.nombre = nombre
        self.precio = precio
        self.stock = stock
    
    def __str__(self):
        return f'{self.nombre} - Precio: {self.precio} - Stock: {self.stock}'
    
    def __repr__(self):
        return f"Producto(nombre='{self.nombre}', precio={self.precio}, stock={self.stock})"

prod = Producto('Laptop', 800, 10)

print(prod)        # Laptop - Precio: 800 - Stock: 10
print(repr(prod))  # Producto(nombre='Laptop', precio=800, stock=10)
Metodos de comparacion
class Temperatura:
    def __init__(self, celsius):
        self.celsius = celsius
    
    def __eq__(self, other):  # ==
        return self.celsius == other.celsius
    
    def __lt__(self, other):  # <
        return self.celsius < other.celsius
    
    def __le__(self, other):  # <=
        return self.celsius <= other.celsius
    
    def __gt__(self, other):  # >
        return self.celsius > other.celsius
    
    def __str__(self):
        return f'{self.celsius}C'

t1 = Temperatura(20)
t2 = Temperatura(35)
t3 = Temperatura(20)

print(t1 == t3)  # True
print(t1 < t2)   # True

temps = [Temperatura(30), Temperatura(15), Temperatura(25)]
para t in sorted(temps):
    print(t, end=' ')  # 15C 25C 30C
Metodos aritmeticos
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 __sub__(self, other):    # -
        return Vector(self.x - other.x, self.y - other.y)
    
    def __mul__(self, escalar):  # *
        return Vector(self.x * escalar, self.y * escalar)
    
    def __abs__(self):           # abs()
        return (self.x**2 + self.y**2) ** 0.5
    
    def __str__(self):
        return f'Vector({self.x}, {self.y})'

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

print(v1 + v2)  # Vector(4, 6)
print(v1 - v2)  # Vector(2, 2)
print(v1 * 3)   # Vector(9, 12)
print(abs(v1))  # 5.0
Metodos de contenedor
class Inventario:
    def __init__(self):
        self.productos = {}
    
    def __setitem__(self, clave, valor):   # inv[clave] = valor
        self.productos[clave] = valor
    
    def __getitem__(self, clave):           # inv[clave]
        return self.productos[clave]
    
    def __delitem__(self, clave):           # del inv[clave]
        del self.productos[clave]
    
    def __contains__(self, clave):          # clave in inv
        return clave in self.productos
    
    def __len__(self):                      # len(inv)
        return len(self.productos)
    
    def __iter__(self):                     # for x in inv
        return iter(self.productos)

inv = Inventario()
inv['laptop'] = 10
inv['mouse'] = 50

print(inv['laptop'])     # 10
print(len(inv))          # 2
print('mouse' in inv)    # True

for p in inv:
    print(f'{p}: {inv[p]}')

del inv['mouse']
print(len(inv))          # 1
call: Objetos invocables
class Validador:
    def __init__(self, minimo, maximo):
        self.minimo = minimo
        self.maximo = maximo
    
    def __call__(self, valor):
        if not isinstance(valor, (int, float)):
            return False, 'Debe ser un numero'
        if valor < self.minimo:
            return False, f'Debe ser mayor o igual a {self.minimo}'
        if valor > self.maximo:
            return False, f'Debe ser menor o igual a {self.maximo}'
        return True, 'Valido'

validar_edad = Validador(0, 120)

for valor in [25, -5, 150, 'abc']:
    valido, msg = validar_edad(valor)
    print(f'{valor}: {msg}')
Context managers
class ConexionBD:
    def __init__(self, nombre):
        self.nombre = nombre
        self.conectado = False
    
    def __enter__(self):
        print(f'Conectando a {self.nombre}...')
        self.conectado = True
        return self
    
    def __exit__(self, tipo_exc, valor_exc, tb):
        print(f'Cerrando conexion a {self.nombre}')
        self.conectado = False
        return False
    
    def ejecutar(self, query):
        if not self.conectado:
            raise RuntimeError('Sin conexion')
        print(f'Ejecutando: {query}')
        return [{'id': 1}]

with ConexionBD('mi_bd') as db:
    res = db.ejecutar('SELECT * FROM usuarios')
    print(f'Resultados: {res}')

print(f'Conectado: {db.conectado}')  # False
💡 Concepto Clave

Revisemos los puntos más importantes de esta lección antes de continuar.

Resumen de metodos especiales

Metodo Cuando se llama
init Al crear el objeto
str print() o str()
repr repr()
len len()
eq ==
lt <
add +
getitem obj[clave]
contains in
iter for en el objeto
call obj()
enter/exit with

En la proxima leccion aplicaremos todo en un proyecto OOP completo.

🧠 Pon a prueba tu conocimiento
¿Cuál es el aspecto más importante que aprendiste en esta lección?
  • Comprendo el concepto principal y puedo explicarlo con mis palabras
  • Entiendo cómo aplicarlo en mi situación específica
  • Necesito repasar algunas partes antes de continuar
  • Quiero ver más ejemplos prácticos del tema
✅ ¡Excelente! Continúa con la siguiente lección para profundizar más.