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:
  • Distinguir entre atributos de instancia y atributos de clase, implementando cada uno apropiadamente
  • Aplicar los conceptos de encapsulación mediante atributos públicos y privados
  • Implementar métodos de instancia, de clase y estáticos según las necesidades del programa
  • Desarrollar aplicaciones profesionales utilizando principios de programación orientada a objetos

📚 Conceptos Fundamentales: Atributos de Clase vs Atributos de Instancia

Los atributos de clase son variables que pertenecen a la clase en sí misma y son compartidas por todas las instancias. Se definen directamente en el cuerpo de la clase, fuera de cualquier método. Por el contrario, los atributos de instancia son únicos para cada objeto creado y se definen típicamente en el método __init__. Esta distinción es crucial para el manejo eficiente de la memoria y la organización lógica del código. Los atributos de clase son útiles para datos que deben ser compartidos entre todas las instancias, como contadores globales o configuraciones predeterminadas.

Ejemplo básico de atributos de clase y de instancia Copiar
class Estudiante:
    # Atributo de clase
    universidad = 'Universidad Nacional'
    contador_estudiantes = 0
    
    def __init__(self, nombre, carrera):
        # Atributos de instancia
        self.nombre = nombre
        self.carrera = carrera
        Estudiante.contador_estudiantes += 1
    
    def mostrar_info(self):
        return f'{self.nombre} estudia {self.carrera} en {self.universidad}'

# Creación de instancias
estudiante1 = Estudiante('Ana', 'Ingeniería')
estudiante2 = Estudiante('Carlos', 'Medicina')

print(estudiante1.mostrar_info())
print(estudiante2.mostrar_info())
print(f'Total estudiantes: {Estudiante.contador_estudiantes}')
Ana estudia Ingeniería en Universidad Nacional
Carlos estudia Medicina en Universidad Nacional
Total estudiantes: 2
Explicación: El atributo 'universidad' es compartido por todas las instancias, mientras que 'nombre' y 'carrera' son únicos para cada estudiante.

🎯 Atributos Públicos y Privados: Encapsulación en Python

La encapsulación es un principio fundamental de la POO que permite controlar el acceso a los datos de una clase. En Python, los atributos públicos son accesibles desde cualquier parte del código, mientras que los atributos privados (precedidos por doble guión bajo __) están destinados a ser utilizados solo dentro de la clase. Los atributos protegidos (con un solo guión bajo _) son una convención que indica que el atributo es para uso interno pero técnicamente sigue siendo accesible. Esta práctica mejora la seguridad del código y facilita el mantenimiento al establecer interfaces claras.

Implementación de atributos públicos, protegidos y privados Copiar
class CuentaBancaria:
    def __init__(self, titular, saldo_inicial):
        self.titular = titular          # Público
        self._numero_cuenta = 12345     # Protegido
        self.__saldo = saldo_inicial    # Privado
    
    def consultar_saldo(self):
        return self.__saldo
    
    def depositar(self, cantidad):
        if cantidad > 0:
            self.__saldo += cantidad
            return f'Depósito exitoso. Saldo actual: ${self.__saldo}'
        return 'Cantidad inválida'
    
    def _validar_retiro(self, cantidad):
        return cantidad > 0 and cantidad <= self.__saldo

cuenta = CuentaBancaria('Juan Pérez', 1000)
print(f'Titular: {cuenta.titular}')
print(cuenta.consultar_saldo())
print(cuenta.depositar(500))
# print(cuenta.__saldo)  # Esto causaría un error
print(f'Número de cuenta: {cuenta._numero_cuenta}')
Titular: Juan Pérez
1000
Depósito exitoso. Saldo actual: $1500
Número de cuenta: 12345
Explicación: Los atributos privados solo son accesibles a través de métodos de la clase, proporcionando control sobre cómo se manipulan los datos sensibles.

💡 Métodos de Clase y Métodos Estáticos

Los métodos de clase (@classmethod) reciben la clase como primer parámetro (convencionalmente llamado 'cls') y pueden acceder a atributos de clase pero no a atributos de instancia. Son útiles para crear constructores alternativos o para operaciones que afectan a toda la clase. Los métodos estáticos (@staticmethod) no reciben automáticamente ningún parámetro especial y funcionan como funciones normales pero están organizados dentro de la clase por razones lógicas. Ambos tipos de métodos se pueden llamar desde la clase sin necesidad de crear una instancia.

Implementación de métodos de clase y estáticos Copiar
class Producto:
    iva = 0.21  # Atributo de clase
    total_productos = 0
    
    def __init__(self, nombre, precio):
        self.nombre = nombre
        self.precio = precio
        Producto.total_productos += 1
    
    @classmethod
    def cambiar_iva(cls, nuevo_iva):
        cls.iva = nuevo_iva
        return f'IVA actualizado a {nuevo_iva}'
    
    @classmethod
    def crear_producto_oferta(cls, nombre, precio_original, descuento):
        precio_final = precio_original * (1 - descuento)
        return cls(nombre, precio_final)
    
    @staticmethod
    def es_precio_valido(precio):
        return precio > 0
    
    def precio_con_iva(self):
        return self.precio * (1 + self.iva)

# Uso de métodos de clase y estáticos
print(Producto.es_precio_valido(100))
print(Producto.cambiar_iva(0.18))
producto_oferta = Producto.crear_producto_oferta('Laptop', 1000, 0.15)
print(f'{producto_oferta.nombre}: ${producto_oferta.precio}')
print(f'Total productos: {Producto.total_productos}')
True
IVA actualizado a 0.18
Laptop: $850.0
Total productos: 1
Explicación: Los métodos de clase permiten operaciones a nivel de clase, mientras que los métodos estáticos proporcionan funciones utilitarias relacionadas con la clase.

🔧 Casos de Uso Avanzados: Sistema de Gestión Empresarial

En aplicaciones empresariales reales, la combinación de atributos y métodos de clase con instancia permite crear sistemas robustos y escalables. Un ejemplo típico es un sistema de gestión de empleados donde necesitamos rastrear información tanto individual como corporativa. Los atributos de clase pueden almacenar políticas empresariales, mientras que los métodos de clase pueden generar reportes o actualizar configuraciones globales. Los atributos privados protegen información sensible como salarios, y los métodos estáticos proporcionan funciones de validación que pueden usarse independientemente de las instancias.

Sistema completo de gestión de empleados Copiar
class Empleado:
    # Atributos de clase
    empresa = 'TechCorp'
    salario_minimo = 30000
    _contador_empleados = 0
    
    def __init__(self, nombre, departamento, salario):
        self.nombre = nombre
        self.departamento = departamento
        self.__salario = salario
        self._id_empleado = self._generar_id()
        Empleado._contador_empleados += 1
    
    @classmethod
    def _generar_id(cls):
        return f'EMP{cls._contador_empleados + 1:04d}'
    
    @classmethod
    def actualizar_salario_minimo(cls, nuevo_minimo):
        cls.salario_minimo = nuevo_minimo
        return f'Salario mínimo actualizado a ${nuevo_minimo}'
    
    @staticmethod
    def validar_departamento(departamento):
        departamentos_validos = ['IT', 'RRHH', 'Ventas', 'Finanzas']
        return departamento in departamentos_validos
    
    def obtener_salario(self):
        return self.__salario
    
    def aumentar_salario(self, porcentaje):
        self.__salario *= (1 + porcentaje / 100)
        return f'Salario aumentado. Nuevo salario: ${self.__salario:.2f}'

# Implementación del sistema
emp1 = Empleado('María García', 'IT', 45000)
emp2 = Empleado('Pedro López', 'Ventas', 35000)

print(f'Empleado: {emp1.nombre}, ID: {emp1._id_empleado}')
print(f'¿IT es válido? {Empleado.validar_departamento("IT")}')
print(emp1.aumentar_salario(10))
print(f'Total empleados: {Empleado._contador_empleados}')
Empleado: María García, ID: EMP0001
¿IT es válido? True
Salario aumentado. Nuevo salario: $49500.00
Total empleados: 2
Explicación: Este ejemplo integra todos los conceptos: atributos públicos/privados, métodos de instancia/clase/estáticos en un sistema funcional real.

Ejercicios Prácticos

Sistema de Biblioteca Digital
INTERMEDIO

Descripción:

Crea una clase Libro con atributos de clase para el total de libros y la biblioteca. Implementa atributos privados para ISBN, métodos de clase para cambiar la biblioteca, y métodos estáticos para validar ISBN. Incluye métodos de instancia para préstamo y devolución.

Pista: Usa un contador de clase para el total de libros y un atributo privado para el estado de préstamo. El método de validación de ISBN puede verificar que tenga 13 dígitos.
Sistema de Vehículos
AVANZADO

Descripción:

Diseña una jerarquía de clases para un concesionario. La clase base Vehiculo debe tener atributos de clase para el concesionario y métodos para calcular impuestos. Implementa atributos privados para el precio y métodos de clase para estadísticas de ventas.

Pista: Considera usar métodos de clase para crear diferentes tipos de vehículos con configuraciones predeterminadas y métodos estáticos para cálculos de impuestos.
Gestión de Cursos Universitarios
BÁSICO

Descripción:

Implementa un sistema donde la clase Curso tenga atributos de clase para la universidad y semestre actual. Los atributos de instancia deben incluir lista privada de estudiantes inscritos. Agrega métodos de clase para cambiar semestre y métodos estáticos para validar códigos de curso.

Pista: Usa una lista privada para los estudiantes y proporciona métodos públicos para inscribir y dar de baja estudiantes de forma controlada.
Sistema Bancario Completo
AVANZADO

Descripción:

Desarrolla un sistema bancario con clases para diferentes tipos de cuentas. Implementa atributos de clase para tasas de interés, atributos privados para saldos, métodos de clase para actualizar tasas, y métodos estáticos para validar números de cuenta.

Pista: Considera implementar diferentes tipos de cuentas (ahorro, corriente) como subclases con sus propias tasas de interés y restricciones.

Resumen y Próximos Pasos

Los atributos y métodos de clase son herramientas poderosas que permiten crear aplicaciones Python más organizadas y eficientes. La comprensión de la encapsulación mediante atributos públicos y privados, junto con el uso apropiado de métodos de instancia, clase y estáticos, forma la base para el desarrollo de software profesional. Estos conceptos son fundamentales para avanzar hacia temas más complejos como herencia, polimorfismo y patrones de diseño. El dominio de estos principios es esencial para cualquier ingeniero de software que busque crear aplicaciones robustas y mantenibles.

🏷️ Etiquetas:
python programación POO atributos métodos encapsulación