La programación orientada a objetos (POO) organiza el código en objetos: datos (atributos) y comportamiento (métodos) que viven juntos. Es la forma natural de modelar cosas del mundo real: una cuenta bancaria, un usuario, un carro.
Clases e instancias
Una clase es el molde; una instancia (u objeto) es cada ejemplar concreto:
class Perro:
def __init__(self, nombre, edad):
self.nombre = nombre # atributo de la instancia
self.edad = edad
def ladrar(self): # método
return f"{self.nombre} dice: ¡guau!"
firulais = Perro("Firulais", 3) # crear instancia
toby = Perro("Toby", 5) # otra instancia independiente
print(firulais.ladrar()) # Firulais dice: ¡guau!
print(toby.edad) # 5
¿Qué es self?
self es la instancia actual. Cuando llamas firulais.ladrar(), Python internamente hace Perro.ladrar(firulais): ese primer parámetro recibe al objeto. Siempre va primero en los métodos, aunque nunca lo pasas tú manualmente.
__init__ es el constructor: se ejecuta al crear la instancia y configura sus atributos iniciales.
Atributos de clase vs de instancia
class Contador:
total_creados = 0 # atributo de CLASE: compartido
def __init__(self):
self.cuenta = 0 # atributo de INSTANCIA: por objeto
Contador.total_creados += 1
a = Contador()
b = Contador()
print(a.cuenta) # 0 (propio de a)
print(Contador.total_creados) # 2 (compartido por todos)
Herencia
Una clase puede extender a otra y reutilizar su comportamiento:
class Animal:
def __init__(self, nombre):
self.nombre = nombre
def presentarse(self):
return f"Soy {self.nombre}"
class Gato(Animal):
def presentarse(self): # SOBRESCRIBE el método del padre
return f"{super().presentarse()} y soy un gato"
michi = Gato("Michi")
print(michi.presentarse()) # Soy Michi y soy un gato
Gato(Animal)→ Gato hereda de Animalsuper()accede a la implementación del padre- Si el hijo redefine un método, el suyo gana (polimorfismo)
Polimorfismo
Distintas clases responden a la misma interfaz:
class Cuadrado:
def area(self):
return self.lado ** 2
class Circulo:
def area(self):
return 3.14159 * self.radio ** 2
for figura in [Cuadrado(), Circulo()]: # no importa el tipo concreto
print(figura.area()) # todas saben calcular su área
Python practica el duck typing: si camina como pato y grazna como pato, es un pato. No necesitas heredar de una clase común para que dos objetos sean intercambiables — basta con que tengan el método.
Métodos especiales (dunder)
Los métodos con doble guion bajo conectan tus clases con la sintaxis de Python:
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __repr__(self): # cómo se "imprime" el objeto
return f"Vector({self.x}, {self.y})"
def __eq__(self, otro): # qué significa ==
return self.x == otro.x and self.y == otro.y
def __len__(self): # qué devuelve len(objeto)
return 2
Resumen
- La clase es el molde;
__init__configura cada instancia selfes la instancia actual; los atributos de instancia viven en cada objeto- La herencia reutiliza;
super()llama al padre; sobrescribir es polimorfismo - Los métodos dunder (
__repr__,__eq__...) integran tu clase con el lenguaje