Volver al curso

Python Desde Cero

leccion
14 / 21
beginner
20 horas
Programacion Orientada a Objetos

Clases y Objetos: El Paradigma OOP desde Cero

Lectura
25 min~4 min lectura

Clases y Objetos: El Paradigma OOP desde Cero

Hasta ahora hemos escrito codigo procedural: instrucciones que se ejecutan de arriba a abajo. La Programacion Orientada a Objetos (OOP) organiza el codigo en torno a objetos que tienen datos (atributos) y comportamiento (metodos).

Por que OOP

Imagina un juego con 100 personajes. Sin OOP necesitas variables separadas para cada uno. Con OOP defines una clase (plantilla) y creas todos los objetos que necesites:

class Personaje:
    def __init__(self, nombre, vida, ataque):
        self.nombre = nombre
        self.vida = vida
        self.ataque = ataque

guerrero = Personaje('Guerrero', 100, 25)
mago = Personaje('Mago', 80, 40)
Que es una clase

Una clase es una plantilla. Un objeto es una instancia concreta de esa clase.

  • Clase = Plano de una casa / Objeto = La casa
  • Clase = Receta de pizza / Objeto = La pizza
Crear tu primera clase
class CuentaBancaria:
    def __init__(self, titular, saldo_inicial=0):
        self.titular = titular
        self.saldo = saldo_inicial
        self.transacciones = []
    
    def depositar(self, monto):
        if monto <= 0:
            raise ValueError('El monto debe ser positivo')
        self.saldo += monto
        self.transacciones.append(('deposito', monto))
        print(f'Deposito exitoso. Saldo: {self.saldo}')
    
    def retirar(self, monto):
        if monto > self.saldo:
            raise ValueError('Saldo insuficiente')
        self.saldo -= monto
        self.transacciones.append(('retiro', monto))
        print(f'Retiro exitoso. Saldo: {self.saldo}')
    
    def ver_saldo(self):
        print(f'Titular: {self.titular}')
        print(f'Saldo: {self.saldo}')
    
    def historial(self):
        print(f'Historial de {self.titular}:')
        for tipo, monto in self.transacciones:
            signo = '+' if tipo == 'deposito' else '-'
            print(f'  {signo} {monto}')
Crear objetos
cuenta_ana = CuentaBancaria('Ana Garcia', 1000)
cuenta_carlos = CuentaBancaria('Carlos Lopez')

cuenta_ana.ver_saldo()
cuenta_ana.depositar(500)
cuenta_ana.retirar(200)
cuenta_ana.historial()

cuenta_carlos.depositar(300)

print(cuenta_ana.saldo)    # 1300
print(cuenta_carlos.saldo) # 300
El parametro self

self es una referencia al objeto actual. Cuando Python ejecuta cuenta_ana.depositar(500), internamente lo convierte en CuentaBancaria.depositar(cuenta_ana, 500).

class Coche:
    def __init__(self, marca, modelo, anio):
        self.marca = marca
        self.modelo = modelo
        self.anio = anio
        self.velocidad = 0
    
    def acelerar(self, incremento):
        self.velocidad += incremento
        print(f'{self.marca} {self.modelo}: {self.velocidad} km/h')
    
    def frenar(self):
        self.velocidad = max(0, self.velocidad - 20)
        print(f'Frenando: {self.velocidad} km/h')

mi_coche = Coche('Toyota', 'Corolla', 2023)
tu_coche = Coche('Honda', 'Civic', 2022)

mi_coche.acelerar(60)
tu_coche.acelerar(80)

print(mi_coche.velocidad)  # 60
print(tu_coche.velocidad)  # 80
Atributos de clase vs atributos de instancia
class Estudiante:
    universidad = 'Universidad Nacional'  # Atributo de CLASE
    total_estudiantes = 0
    
    def __init__(self, nombre, carrera):
        self.nombre = nombre  # Atributo de INSTANCIA
        self.carrera = carrera
        self.notas = []
        Estudiante.total_estudiantes += 1
    
    def agregar_nota(self, nota):
        self.notas.append(nota)
    
    def promedio(self):
        if not self.notas:
            return 0
        return sum(self.notas) / len(self.notas)

est1 = Estudiante('Ana', 'Informatica')
est2 = Estudiante('Carlos', 'Medicina')

est1.agregar_nota(90)
est1.agregar_nota(85)
print(f'Promedio: {est1.promedio():.1f}')

print(est1.universidad)             # Universidad Nacional
print(Estudiante.total_estudiantes) # 2
Encapsulacion: Proteger datos
class CuentaSegura:
    def __init__(self, titular, pin, saldo=0):
        self.titular = titular
        self.__pin = pin      # privado (doble guion bajo)
        self.__saldo = saldo  # privado
    
    def verificar_pin(self, pin_ingresado):
        return self.__pin == pin_ingresado
    
    def get_saldo(self, pin):
        if not self.verificar_pin(pin):
            raise PermissionError('PIN incorrecto')
        return self.__saldo
    
    def depositar(self, monto, pin):
        if not self.verificar_pin(pin):
            raise PermissionError('PIN incorrecto')
        self.__saldo += monto
        return self.__saldo

cuenta = CuentaSegura('Ana', '1234', 500)

print(cuenta.get_saldo('1234'))   # 500
cuenta.depositar(200, '1234')
print(cuenta.get_saldo('1234'))   # 700

try:
    cuenta.get_saldo('9999')
except PermissionError as e:
    print(f'Error: {e}')
Proyecto: Sistema de empleados
class Empleado:
    empresa = 'TechCorp SA'
    
    def __init__(self, nombre, cargo, salario_base):
        self.nombre = nombre
        self.cargo = cargo
        self.salario_base = salario_base
        self.bonos = []
    
    def agregar_bono(self, monto, razon):
        self.bonos.append({'monto': monto, 'razon': razon})
        print(f'Bono de {monto} a {self.nombre}: {razon}')
    
    def salario_total(self):
        return self.salario_base + sum(b['monto'] for b in self.bonos)
    
    def resumen(self):
        print(f'--- {self.nombre} ---')
        print(f'Cargo: {self.cargo}')
        print(f'Empresa: {self.empresa}')
        print(f'Salario total: {self.salario_total()}')

ana = Empleado('Ana Garcia', 'Desarrolladora Senior', 5000)
carlos = Empleado('Carlos Mendez', 'Disenador', 3500)

ana.agregar_bono(1000, 'Proyecto exitoso')
ana.agregar_bono(500, 'Horas extra')
carlos.agregar_bono(750, 'Diseno de marca')

ana.resumen()
carlos.resumen()
💡 Concepto Clave

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

Resumen

  • Una clase es una plantilla para crear objetos
  • Un objeto es una instancia de una clase
  • init es el constructor
  • self referencia al objeto actual
  • Los atributos guardan datos, los metodos definen comportamiento
  • La encapsulacion (doble guion bajo) protege datos internos

En la proxima leccion: herencia y polimorfismo.

🧠 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.