Lección Python

Contenido de la lección

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 los conceptos fundamentales de la Programación Orientada a Objetos
  • Aprender a definir clases y crear objetos en Python
  • Dominar la sintaxis para atributos de instancia y métodos de clase
  • Implementar casos de uso reales usando clases y objetos
  • Aplicar principios de encapsulación básica en el diseño de clases

📚 Conceptos Fundamentales de POO

La Programación Orientada a Objetos se basa en cuatro pilares fundamentales: encapsulación, herencia, polimorfismo y abstracción. En este tema nos enfocaremos en los elementos básicos: clases y objetos. Una CLASE es un molde o plantilla que define las características y comportamientos que tendrán los objetos. Un OBJETO es una instancia específica de una clase, con valores particulares para sus atributos. Los ATRIBUTOS son las características o propiedades que describe un objeto (como color, tamaño, nombre). Los MÉTODOS son las funciones que definen los comportamientos o acciones que puede realizar un objeto. La POO nos permite organizar el código de manera modular, reutilizable y más cercana a como pensamos naturalmente sobre los problemas del mundo real.

Estructura básica de una clase en Python Copiar
# Definición básica de una clase
class Persona:
    pass  # Clase vacía por ahora

# Crear un objeto (instancia) de la clase
persona1 = Persona()
print(type(persona1))
print(persona1)
Salida:

<__main__.Persona object at 0x...>
Explicación: Este ejemplo muestra la sintaxis básica para definir una clase vacía y crear una instancia. La palabra clave 'class' define la clase, y llamar a Persona() crea un objeto de esa clase.

🎯 Definición de Clases con Atributos

Los atributos son variables que pertenecen a una clase y almacenan datos específicos de cada objeto. En Python, los atributos se pueden definir de varias maneras. Los atributos de instancia son únicos para cada objeto y se definen típicamente en el método especial __init__, que es el constructor de la clase. Este método se ejecuta automáticamente cuando se crea un nuevo objeto. Los atributos de clase son compartidos por todas las instancias de la clase. Es importante entender la diferencia entre estos tipos de atributos para diseñar clases efectivas. El método __init__ recibe como primer parámetro 'self', que es una referencia al objeto que se está creando, permitiendo acceder y modificar sus atributos específicos.

Clase con constructor y atributos de instancia Copiar
class Estudiante:
    # Atributo de clase (compartido por todas las instancias)
    universidad = 'Universidad Técnica'
    
    def __init__(self, nombre, edad, carrera):
        # Atributos de instancia (únicos para cada objeto)
        self.nombre = nombre
        self.edad = edad
        self.carrera = carrera

# Crear objetos con diferentes valores
estudiante1 = Estudiante('Ana', 20, 'Ingeniería de Sistemas')
estudiante2 = Estudiante('Carlos', 22, 'Ingeniería Civil')

print(f'Estudiante 1: {estudiante1.nombre}, {estudiante1.edad} años')
print(f'Carrera: {estudiante1.carrera}')
print(f'Universidad: {estudiante1.universidad}')
print(f'Estudiante 2: {estudiante2.nombre}, {estudiante2.edad} años')
Estudiante 1: Ana, 20 años
Carrera: Ingeniería de Sistemas
Universidad: Universidad Técnica
Estudiante 2: Carlos, 22 años
Explicación: El constructor __init__ inicializa los atributos de instancia. Cada objeto tiene sus propios valores para nombre, edad y carrera, pero comparten el atributo de clase 'universidad'.

💡 Métodos de Instancia

Los métodos son funciones definidas dentro de una clase que determinan el comportamiento de los objetos. Los métodos de instancia son los más comunes y siempre reciben 'self' como primer parámetro, lo que les permite acceder y modificar los atributos del objeto. Los métodos pueden recibir parámetros adicionales y retornar valores, al igual que las funciones normales. Es una buena práctica crear métodos para acceder y modificar atributos (getters y setters), realizar cálculos basados en los atributos del objeto, o ejecutar acciones específicas relacionadas con el objeto. Los métodos encapsulan la lógica relacionada con los datos, manteniendo la cohesión del código y facilitando el mantenimiento.

Clase con métodos de instancia para realizar operaciones Copiar
class CuentaBancaria:
    def __init__(self, titular, saldo_inicial=0):
        self.titular = titular
        self.saldo = saldo_inicial
        self.historial = []
    
    def depositar(self, cantidad):
        if cantidad > 0:
            self.saldo += cantidad
            self.historial.append(f'Depósito: +${cantidad}')
            return True
        return False
    
    def retirar(self, cantidad):
        if cantidad > 0 and cantidad <= self.saldo:
            self.saldo -= cantidad
            self.historial.append(f'Retiro: -${cantidad}')
            return True
        return False
    
    def consultar_saldo(self):
        return f'Saldo actual: ${self.saldo}'
    
    def mostrar_historial(self):
        for transaccion in self.historial:
            print(transaccion)

# Uso de la clase
cuenta = CuentaBancaria('María García', 1000)
print(cuenta.consultar_saldo())
cuenta.depositar(500)
cuenta.retirar(200)
print(cuenta.consultar_saldo())
cuenta.mostrar_historial()
Saldo actual: $1000
Saldo actual: $1300
Depósito: +$500
Retiro: -$200
Explicación: Los métodos permiten realizar operaciones específicas con los datos del objeto. Cada método tiene acceso a los atributos através de 'self' y puede modificar el estado del objeto.

🔧 Múltiples Instancias y Comportamiento Independiente

Una de las ventajas principales de la POO es la capacidad de crear múltiples objetos independientes a partir de la misma clase. Cada objeto mantiene su propio estado y puede ser manipulado de forma independiente. Esto es fundamental para modelar sistemas complejos donde necesitamos múltiples entidades similares pero con características distintas. Los objetos pueden interactuar entre sí através de métodos, lo que permite crear sistemas dinámicos y realistas. Es importante entender que aunque los objetos comparten la misma estructura (definida por la clase), cada uno mantiene sus propios valores de atributos y puede evolucionar de manera independiente durante la ejecución del programa.

Múltiples objetos independientes de la misma clase Copiar
class Vehiculo:
    def __init__(self, marca, modelo, kilometraje=0):
        self.marca = marca
        self.modelo = modelo
        self.kilometraje = kilometraje
        self.encendido = False
    
    def encender(self):
        if not self.encendido:
            self.encendido = True
            return f'{self.marca} {self.modelo} encendido'
        return f'{self.marca} {self.modelo} ya está encendido'
    
    def conducir(self, distancia):
        if self.encendido:
            self.kilometraje += distancia
            return f'Conducido {distancia} km. Total: {self.kilometraje} km'
        return 'Debe encender el vehículo primero'
    
    def apagar(self):
        self.encendido = False
        return f'{self.marca} {self.modelo} apagado'

# Crear varios vehículos independientes
auto1 = Vehiculo('Toyota', 'Corolla')
auto2 = Vehiculo('Honda', 'Civic', 15000)
moto1 = Vehiculo('Yamaha', 'MT-07')

# Operar cada vehículo independientemente
print(auto1.encender())
print(auto1.conducir(50))
print(auto2.encender())
print(auto2.conducir(100))
print(f'Auto1 kilometraje: {auto1.kilometraje}')
print(f'Auto2 kilometraje: {auto2.kilometraje}')
Toyota Corolla encendido
Conducido 50 km. Total: 50 km
Honda Civic encendido
Conducido 100 km. Total: 15100 km
Auto1 kilometraje: 50
Auto2 kilometraje: 15100
Explicación: Cada objeto mantiene su estado independiente. auto1 y auto2 son instancias separadas que pueden ser operadas de forma independiente, manteniendo sus propios valores de atributos.

⚡ Casos de Uso Avanzados y Aplicaciones Profesionales

En el desarrollo profesional, las clases y objetos son fundamentales para crear sistemas escalables y mantenibles. Algunos casos de uso comunes incluyen: modelado de entidades de negocio (usuarios, productos, pedidos), implementación de estructuras de datos personalizadas, creación de APIs y servicios web, desarrollo de juegos y simulaciones, y sistemas de gestión de recursos. Las clases permiten encapsular lógica compleja y crear abstracciones que facilitan el trabajo en equipo. En aplicaciones empresariales, es común tener clases que representen conceptos del dominio del negocio, lo que facilita la comunicación entre desarrolladores y stakeholders. La capacidad de crear múltiples instancias permite manejar grandes volúmenes de datos de manera eficiente y organizada.

Sistema de gestión de empleados - caso de uso empresarial Copiar
class Empleado:
    contador_empleados = 0
    
    def __init__(self, nombre, departamento, salario):
        Empleado.contador_empleados += 1
        self.id_empleado = Empleado.contador_empleados
        self.nombre = nombre
        self.departamento = departamento
        self.salario = salario
        self.activo = True
    
    def aumentar_salario(self, porcentaje):
        aumento = self.salario * (porcentaje / 100)
        self.salario += aumento
        return f'Salario aumentado en {porcentaje}%. Nuevo salario: ${self.salario:.2f}'
    
    def transferir_departamento(self, nuevo_departamento):
        depto_anterior = self.departamento
        self.departamento = nuevo_departamento
        return f'{self.nombre} transferido de {depto_anterior} a {nuevo_departamento}'
    
    def obtener_info(self):
        estado = 'Activo' if self.activo else 'Inactivo'
        return f'ID: {self.id_empleado} | {self.nombre} | {self.departamento} | ${self.salario} | {estado}'

# Sistema de gestión
emp1 = Empleado('Juan Pérez', 'Desarrollo', 3000)
emp2 = Empleado('Laura Rodríguez', 'Marketing', 2800)
emp3 = Empleado('Carlos López', 'Ventas', 3200)

print('=== SISTEMA DE EMPLEADOS ===')
print(emp1.obtener_info())
print(emp2.obtener_info())
print(emp3.obtener_info())
print(f'Total empleados: {Empleado.contador_empleados}')
print('\n=== OPERACIONES ===')
print(emp1.aumentar_salario(10))
print(emp2.transferir_departamento('Desarrollo'))
=== SISTEMA DE EMPLEADOS ===
ID: 1 | Juan Pérez | Desarrollo | $3000 | Activo
ID: 2 | Laura Rodríguez | Marketing | $2800 | Activo
ID: 3 | Carlos López | Ventas | $3200 | Activo
Total empleados: 3

=== OPERACIONES ===
Salario aumentado en 10%. Nuevo salario: $3300.00
Laura Rodríguez transferido de Marketing a Desarrollo
Explicación: Este ejemplo muestra un caso de uso empresarial real donde las clases encapsulan la lógica de negocio. El contador de clase rastrea el total de empleados, y cada instancia maneja operaciones específicas del empleado.

Ejercicios Prácticos

Crear una Clase Libro
BÁSICO

Descripción:

Define una clase Libro con atributos titulo, autor, paginas y disponible (booleano). Implementa métodos para prestar el libro, devolverlo y mostrar información. Crea al menos 3 libros diferentes y simula operaciones de préstamo.

Pista: Recuerda usar el método __init__ para inicializar los atributos y self para acceder a ellos en los métodos.
Sistema de Productos de Tienda
INTERMEDIO

Descripción:

Crea una clase Producto con nombre, precio, stock y código. Implementa métodos para agregar stock, vender productos (reducir stock), aplicar descuentos y calcular valor total del inventario. Crea un inventario con 5 productos diferentes.

Pista: Considera validaciones para evitar stock negativo y asegúrate de que los precios sean positivos.
Simulador de Cuentas Bancarias Avanzado
AVANZADO

Descripción:

Extiende el ejemplo de CuentaBancaria agregando tipos de cuenta (ahorros, corriente), límites de retiro, intereses mensuales y la capacidad de transferir dinero entre cuentas. Simula un mes de operaciones bancarias.

Pista: Usa atributos de clase para definir tasas de interés y límites por tipo de cuenta. Implementa validaciones robustas.
Registro de Estudiantes Universitarios
INTERMEDIO

Descripción:

Diseña una clase EstudianteUniversitario con carnet, nombre, carrera, semestre, materias inscritas y calificaciones. Implementa métodos para inscribir materias, registrar calificaciones, calcular promedio y determinar estado académico.

Pista: Usa listas para manejar materias y diccionarios para relacionar materias con calificaciones.

Resumen y Próximos Pasos

En esta introducción a POO hemos establecido los fundamentos esenciales: clases como plantillas, objetos como instancias, atributos para almacenar datos y métodos para definir comportamientos. Estos conceptos forman la base sobre la cual construiremos conocimientos más avanzados como herencia, polimorfismo y encapsulación. La práctica con múltiples ejemplos y ejercicios consolida la comprensión de cómo modelar problemas reales usando POO. En el próximo tema exploraremos métodos especiales y propiedades avanzadas que nos permitirán crear clases más sofisticadas y funcionales, acercándonos cada vez más a aplicaciones profesionales complejas.

🏷️ Etiquetas:
python programación POO clases objetos ingeniería