Programación Orientada a Objetos en Python: Clases y Objetos

🐍 Python — POO

Programación Orientada a Objetos en Python: Clases, Objetos y Herencia

Aprende Programación Orientada a Objetos (POO) en Python desde cero. Clases, objetos, atributos, métodos, herencia y polimorfismo con ejercicios resueltos paso a paso.

⏱ 18 min de lectura 🎯 Intermedio 💻 Código ejecutable ✅ Ejercicios resueltos

1¿Qué es la Programación Orientada a Objetos?

La Programación Orientada a Objetos (POO) es un paradigma que organiza el código en torno a objetos: entidades que combinan datos (atributos) y comportamientos (métodos). Es la base de frameworks como Django y librerías como Pandas.

💡 Analogía del mundo real
Piensa en un automóvil: tiene atributos (color, marca, velocidad) y comportamientos (acelerar, frenar, girar). En POO, defines una clase Automovil como plano, y cada auto específico que creates es un objeto.
ConceptoAnalogíaEn Python
ClasePlano arquitectónicoclass Persona:
ObjetoCasa construida con ese planop = Persona("Ana")
AtributoCaracterísticas (color, tamaño)p.nombre = "Ana"
MétodoAcciones (abrir puerta, encender luz)p.saludar()

2Crear una clase: class e __init__

Una clase se define con la palabra clave class. El método especial __init__ es el constructor: se ejecuta automáticamente cuando se crea un objeto.

primera_clase.py
class Persona:
    """Clase que representa a una persona"""

    def __init__(self, nombre, edad):
        # Atributos de instancia
        self.nombre = nombre
        self.edad   = edad

    def saludar(self):
        print(f"Hola, me llamo {self.nombre} y tengo {self.edad} años")

    def cumpleanos(self):
        self.edad += 1
        print(f"🎂 ¡Feliz cumpleaños {self.nombre}! Ahora tienes {self.edad} años")


# Crear objetos (instancias) de la clase
persona1 = Persona("Ana", 25)
persona2 = Persona("Luis", 30)

# Llamar métodos
persona1.saludar()
persona2.saludar()
persona1.cumpleanos()

# Acceder a atributos directamente
print(f"Nombre: {persona1.nombre}, Edad: {persona1.edad}")
▶ Salida
Hola, me llamo Ana y tengo 25 años
Hola, me llamo Luis y tengo 30 años
🎂 ¡Feliz cumpleaños Ana! Ahora tienes 26 años
Nombre: Ana, Edad: 26

3Atributos y métodos

Existen dos tipos de atributos: los de instancia (únicos para cada objeto) y los de clase (compartidos por todos los objetos).

atributos_metodos.py
class CuentaBancaria:
    banco = "Banco Python"   # Atributo de clase (compartido)
    tasa_interes = 0.05       # Atributo de clase

    def __init__(self, titular, saldo_inicial=0):
        self.titular = titular       # Atributo de instancia
        self.saldo   = saldo_inicial  # Atributo de instancia
        self.movimientos = []

    def depositar(self, monto):
        self.saldo += monto
        self.movimientos.append(f"+{monto}")
        print(f"✅ Depósito: ${monto:,.0f} | Saldo: ${self.saldo:,.0f}")

    def retirar(self, monto):
        if monto > self.saldo:
            print("❌ Saldo insuficiente")
        else:
            self.saldo -= monto
            self.movimientos.append(f"-{monto}")
            print(f"💸 Retiro: ${monto:,.0f} | Saldo: ${self.saldo:,.0f}")

    def ver_estado(self):
        print(f"\n=== Cuenta de {self.titular} ({self.banco}) ===")
        print(f"Saldo actual: ${self.saldo:,.0f}")
        print(f"Movimientos: {self.movimientos}")

# Crear y usar la cuenta
cuenta = CuentaBancaria("Ana García", 500000)
cuenta.depositar(200000)
cuenta.retirar(100000)
cuenta.retirar(900000)
cuenta.ver_estado()
▶ Salida
✅ Depósito: $200,000 | Saldo: $700,000
💸 Retiro: $100,000 | Saldo: $600,000
❌ Saldo insuficiente

=== Cuenta de Ana García (Banco Python) ===
Saldo actual: $600,000
Movimientos: ['+200000', '-100000']

4¿Qué es self?

self es una referencia al propio objeto. Cuando llamas cuenta.depositar(200), Python traduce eso internamente a CuentaBancaria.depositar(cuenta, 200). self siempre debe ser el primer parámetro de cada método.

🔑 Regla práctica sobre self
Siempre que quieras acceder o modificar un atributo del objeto dentro de un método, debes usar self.nombre_atributo. Sin self, Python crearía una variable local que desaparece al terminar el método.

5Herencia

La herencia permite crear una clase nueva basada en una existente, reutilizando y extendiendo su funcionalidad. La clase original se llama clase padre y la nueva es la clase hija.

herencia.py
# Clase padre (base)
class Animal:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad   = edad

    def info(self):
        print(f"{self.nombre} ({self.edad} años)")

    def sonido(self):
        print("... (sonido genérico)")


# Clases hijas (heredan de Animal)
class Perro(Animal):
    def __init__(self, nombre, edad, raza):
        super().__init__(nombre, edad)  # llama al __init__ del padre
        self.raza = raza

    def sonido(self):  # Sobreescribe el método del padre
        print(f"{self.nombre} dice: ¡Guau guau! 🐕")

    def info(self):
        super().info()   # llama al método del padre
        print(f"  Raza: {self.raza}")


class Gato(Animal):
    def __init__(self, nombre, edad, indoor):
        super().__init__(nombre, edad)
        self.indoor = indoor

    def sonido(self):
        print(f"{self.nombre} dice: ¡Miau! 🐈")


# Crear objetos
perro = Perro("Rex", 3, "Labrador")
gato  = Gato("Luna", 2, True)

perro.info()
perro.sonido()
gato.info()
gato.sonido()
▶ Salida
Rex (3 años)
  Raza: Labrador
Rex dice: ¡Guau guau! 🐕
Luna (2 años)
Luna dice: ¡Miau! 🐈

6Polimorfismo

El polimorfismo permite tratar objetos de distintas clases de forma uniforme. Si todas tienen el mismo método, puedes llamarlo sin importar qué tipo de objeto sea.

polimorfismo.py
# Polimorfismo: mismo método, distintos comportamientos
animales = [
    Perro("Rex",  3, "Labrador"),
    Gato("Luna", 2, True),
    Perro("Max",  5, "Poodle"),
    Gato("Misi", 1, False),
]

print("=== TODOS LOS ANIMALES HACEN RUIDO ===")
for animal in animales:
    animal.sonido()  # cada uno responde diferente
▶ Salida
=== TODOS LOS ANIMALES HACEN RUIDO ===
Rex dice: ¡Guau guau! 🐕
Luna dice: ¡Miau! 🐈
Max dice: ¡Guau guau! 🐕
Misi dice: ¡Miau! 🐈

7🏋️ Ejercicio: Sistema de Biblioteca

📋 Enunciado

Implementa un sistema básico de biblioteca con clases Libro y Biblioteca. Debe permitir agregar libros, buscar por título o autor, y mostrar el catálogo.

biblioteca.py
class Libro:
    def __init__(self, titulo, autor, anio, disponible=True):
        self.titulo     = titulo
        self.autor      = autor
        self.anio       = anio
        self.disponible = disponible

    def __str__(self):
        estado = "✅ Disponible" if self.disponible else "❌ Prestado"
        return f'"{self.titulo}" — {self.autor} ({self.anio}) [{estado}]'


class Biblioteca:
    def __init__(self, nombre):
        self.nombre  = nombre
        self.libros  = []

    def agregar_libro(self, libro):
        self.libros.append(libro)
        print(f"📚 Libro agregado: {libro.titulo}")

    def buscar_titulo(self, texto):
        encontrados = [l for l in self.libros if texto.lower() in l.titulo.lower()]
        print(f"\n🔍 Resultados para '{texto}':")
        for l in encontrados: print(f"  {l}")
        return encontrados

    def prestar(self, titulo):
        for libro in self.libros:
            if libro.titulo == titulo:
                if libro.disponible:
                    libro.disponible = False
                    print(f"📖 Prestado: {titulo}")
                else:
                    print(f"❌ No disponible: {titulo}")
                return
        print("Libro no encontrado")

    def catalogo(self):
        print(f"\n=== {self.nombre} — Catálogo ({len(self.libros)} libros) ===")
        for libro in self.libros:
            print(f"  {libro}")


# Prueba del sistema
bib = Biblioteca("Biblioteca Central")
bib.agregar_libro(Libro("Python Crash Course",  "Eric Matthes",   2019))
bib.agregar_libro(Libro("Automate with Python", "Al Sweigart",    2020))
bib.agregar_libro(Libro("Fluent Python",       "Luciano Ramalho", 2022))

bib.catalogo()
bib.prestar("Fluent Python")
bib.prestar("Fluent Python")  # Intento de nuevo préstamo
bib.catalogo()
▶ Salida
📚 Libro agregado: Python Crash Course
📚 Libro agregado: Automate with Python
📚 Libro agregado: Fluent Python

=== Biblioteca Central — Catálogo (3 libros) ===
  "Python Crash Course" — Eric Matthes (2019) [✅ Disponible]
  "Automate with Python" — Al Sweigart (2020) [✅ Disponible]
  "Fluent Python" — Luciano Ramalho (2022) [✅ Disponible]
📖 Prestado: Fluent Python
❌ No disponible: Fluent Python

=== Biblioteca Central — Catálogo (3 libros) ===
  "Python Crash Course" — Eric Matthes (2019) [✅ Disponible]
  "Automate with Python" — Al Sweigart (2020) [✅ Disponible]
  "Fluent Python" — Luciano Ramalho (2022) [❌ Prestado]

¿Aprendiste POO en Python? 🏆

¡Déjanos tus preguntas en los comentarios! Comparte con tus compañeros y suscríbete para más ejercicios resueltos cada semana.

PythonPOOClasesHerenciaPolimorfismo
📖 Continúa aprendiendo
  • Manejo de archivos en Python: leer y escribir ficheros
  • Excepciones en Python: try, except, finally
  • Módulos y paquetes en Python

Comentarios

Entradas populares de este blog

Ejercicios de Python para Principiantes: Guía Paso a Paso con Ejemplos

Diccionarios en Python: Guía Completa con Ejemplos