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 la diferencia entre módulos y paquetes en Python
  • Dominar las diferentes formas de importar funcionalidades
  • Crear módulos propios y organizarlos en paquetes
  • Aplicar buenas prácticas de organización de código en proyectos reales

📚 1. Conceptos Fundamentales de Módulos

Un módulo en Python es un archivo que contiene código Python ejecutable. Puede incluir funciones, clases, variables y declaraciones. Los módulos permiten organizar el código de manera lógica y reutilizable. Python incluye una biblioteca estándar extensa con módulos predefinidos como math, os, datetime, entre otros. Cuando importamos un módulo, Python busca el archivo en varios lugares: primero en el directorio actual, luego en PYTHONPATH, y finalmente en directorios de instalación estándar. La importación se puede realizar de varias formas: importando todo el módulo, funciones específicas, o usando alias para nombres más cortos.

Importación básica de módulos de la biblioteca estándar Copiar
import math
import os

# Usar funciones del módulo math
resultado = math.sqrt(16)
print(f'Raíz cuadrada de 16: {resultado}')

# Usar funciones del módulo os
directorio_actual = os.getcwd()
print(f'Directorio actual: {directorio_actual}')
Raíz cuadrada de 16: 4.0
Directorio actual: /home/usuario/proyecto
Explicación: Se importan módulos completos y se accede a sus funciones usando la notación punto (módulo.función)
Importación selectiva y uso de alias Copiar
from math import pi, cos, sin
from datetime import datetime as dt

# Usar funciones importadas directamente
angulo = pi / 4
print(f'cos({angulo}) = {cos(angulo):.3f}')
print(f'sin({angulo}) = {sin(angulo):.3f}')

# Usar alias
ahora = dt.now()
print(f'Fecha actual: {ahora.strftime("%Y-%m-%d %H:%M:%S")}')
cos(0.7853981633974483) = 0.707
sin(0.7853981633974483) = 0.707
Fecha actual: 2024-03-15 14:30:25
Explicación: La importación selectiva permite usar funciones directamente sin prefijo, y los alias simplifican nombres largos

🎯 2. Creación de Módulos Personalizados

Crear módulos propios es esencial para organizar código en proyectos grandes. Un módulo personalizado se crea simplemente guardando código Python en un archivo .py. Este archivo puede contener funciones, clases, constantes y código que se ejecuta al importar. Es importante incluir docstrings para documentar el propósito del módulo y sus componentes. La variable especial __name__ permite diferenciar si el archivo se ejecuta directamente o se importa como módulo. Los módulos pueden tener código de inicialización que se ejecuta solo la primera vez que se importan.

Crear un módulo de utilidades matemáticas (archivo: matematicas_avanzadas.py) Copiar
# matematicas_avanzadas.py
'''
Módulo de utilidades matemáticas avanzadas
'''

def factorial(n):
    '''Calcula el factorial de un número'''
    if n <= 1:
        return 1
    return n * factorial(n - 1)

def es_primo(n):
    '''Verifica si un número es primo'''
    if n < 2:
        return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False
    return True

PI_APROXIMADO = 3.14159

if __name__ == '__main__':
    print('Ejecutando módulo directamente')
    print(f'Factorial de 5: {factorial(5)}')
    print(f'¿Es 17 primo?: {es_primo(17)}')
Ejecutando módulo directamente
Factorial de 5: 120
¿Es 17 primo?: True
Explicación: El bloque if __name__ == '__main__' permite ejecutar código solo cuando el archivo se ejecuta directamente
Importar y usar el módulo personalizado Copiar
import matematicas_avanzadas as mat
from matematicas_avanzadas import factorial, es_primo

# Usar con alias
print(f'PI aproximado: {mat.PI_APROXIMADO}')
print(f'Factorial de 6: {mat.factorial(6)}')

# Usar importación directa
print(f'Factorial de 4: {factorial(4)}')
print(f'¿Es 15 primo?: {es_primo(15)}')

# Verificar nombre del módulo
print(f'Nombre del módulo: {mat.__name__}')
PI aproximado: 3.14159
Factorial de 6: 720
Factorial de 4: 24
¿Es 15 primo?: False
Nombre del módulo: matematicas_avanzadas
Explicación: Se puede importar el módulo completo con alias o funciones específicas, y acceder a sus atributos

💡 3. Introducción a los Paquetes

Un paquete es una forma de organizar módulos relacionados en una estructura de directorios. Los paquetes permiten crear jerarquías de módulos y evitar conflictos de nombres. Para que Python reconozca un directorio como paquete, debe contener un archivo __init__.py (puede estar vacío). Este archivo se ejecuta cuando se importa el paquete por primera vez y puede contener código de inicialización. Los paquetes pueden tener subpaquetes, creando estructuras jerárquicas complejas. La importación de paquetes sigue las mismas reglas que los módulos, pero permite acceso estructurado a funcionalidades organizadas.

Estructura de un paquete de utilidades (crear directorios y archivos) Copiar
# Estructura de directorios:
# utilidades/
#   __init__.py
#   matematicas.py
#   texto.py
#   archivos.py

# utilidades/__init__.py
'''
Paquete de utilidades generales
'''
__version__ = '1.0.0'
print('Inicializando paquete utilidades')

# utilidades/matematicas.py
def suma_lista(lista):
    return sum(lista)

def promedio(lista):
    return sum(lista) / len(lista) if lista else 0

# utilidades/texto.py
def invertir_cadena(texto):
    return texto[::-1]

def contar_palabras(texto):
    return len(texto.split())
Inicializando paquete utilidades
Explicación: La estructura de paquetes organiza módulos relacionados y __init__.py marca el directorio como paquete
Importar y usar componentes del paquete Copiar
# Importar todo el paquete
import utilidades

# Importar módulos específicos
from utilidades import matematicas, texto
from utilidades.matematicas import promedio

# Usar funciones del paquete
numeros = [1, 2, 3, 4, 5]
print(f'Promedio: {matematicas.promedio(numeros)}')
print(f'Suma: {matematicas.suma_lista(numeros)}')

# Usar función importada directamente
print(f'Promedio directo: {promedio([10, 20, 30])}')

# Usar módulo de texto
frase = 'Hola mundo'
print(f'Texto invertido: {texto.invertir_cadena(frase)}')
print(f'Palabras: {texto.contar_palabras(frase)}')

# Verificar versión del paquete
print(f'Versión: {utilidades.__version__}')
Promedio: 3.0
Suma: 15
Promedio directo: 20.0
Texto invertido: odnum aloH
Palabras: 2
Versión: 1.0.0
Explicación: Los paquetes permiten acceso jerárquico a módulos y sus funciones, manteniendo organización clara

🔧 4. Casos de Uso Avanzados y Buenas Prácticas

En proyectos profesionales, la organización modular es crucial. Los paquetes pueden incluir configuraciones, pruebas, documentación y recursos. Es recomendable seguir convenciones como PEP 8 para nombres de módulos (minúsculas con guiones bajos). Los módulos deben tener responsabilidades bien definidas y ser lo más independientes posible. La importación circular debe evitarse diseñando correctamente las dependencias. Los __init__.py pueden controlar qué se importa con 'from paquete import *' usando __all__. En aplicaciones grandes, se usan patrones como factory, singleton o registry implementados a nivel de módulo.

Paquete con configuración y control de importaciones Copiar
# config/__init__.py
__all__ = ['configuracion', 'logger']

from .configuracion import *
from .logger import crear_logger

# config/configuracion.py
DATABASE_URL = 'sqlite:///app.db'
DEBUG = True
VERSION = '2.1.0'

class Config:
    def __init__(self):
        self.database_url = DATABASE_URL
        self.debug = DEBUG
    
    def get_config(self):
        return {'db': self.database_url, 'debug': self.debug}

# config/logger.py
def crear_logger(nombre):
    print(f'Logger creado para: {nombre}')
    return f'Logger-{nombre}'

# Uso del paquete
from config import *
from config import crear_logger

config = Config()
print(f'Configuración: {config.get_config()}')
logger = crear_logger('MiApp')
print(f'Logger: {logger}')
Logger creado para: MiApp
Configuración: {'db': 'sqlite:///app.db', 'debug': True}
Logger: Logger-MiApp
Explicación: __all__ controla qué se importa con *, y la importación relativa (.) organiza módulos internos

Ejercicios Prácticos

Crear un Sistema de Gestión de Estudiantes
INTERMEDIO

Descripción:

Crea un paquete 'universidad' con módulos para 'estudiantes', 'cursos' y 'calificaciones'. Cada módulo debe tener al menos 2 funciones y el paquete debe tener un __init__.py que importe las funciones principales.

Pista: Usa clases para representar entidades y funciones para operaciones. El __init__.py puede importar las clases principales para facilitar su uso.
Módulo de Utilidades de Archivos
BÁSICO

Descripción:

Desarrolla un módulo que contenga funciones para leer, escribir, copiar y obtener información de archivos. Incluye manejo de excepciones y documentación completa.

Pista: Usa los módulos os y shutil de Python. Incluye docstrings en todas las funciones y maneja excepciones FileNotFoundError.
Paquete de Análisis de Datos Básico
AVANZADO

Descripción:

Crea un paquete 'analisis' con módulos para estadísticas básicas, visualización simple y procesamiento de listas. Implementa funciones como media, mediana, moda y generación de reportes.

Pista: Organiza en subpaquetes: estadisticas/, visualizacion/, procesamiento/. Usa __init__.py para crear una API limpia del paquete.
Sistema de Configuración Modular
AVANZADO

Descripción:

Diseña un sistema donde diferentes módulos puedan registrar y acceder a configuraciones globales. Implementa un patrón singleton para el gestor de configuración.

Pista: Crea un módulo config_manager que mantenga un diccionario global de configuraciones y funciones para registrar/obtener valores.

Resumen y Próximos Pasos

Los módulos y paquetes son la base de la programación modular en Python, permitiendo crear aplicaciones escalables y mantenibles. Hemos cubierto desde importaciones básicas hasta estructuras de paquetes complejas con buenas prácticas profesionales. La correcta organización del código facilita el mantenimiento, la reutilización y la colaboración en equipos. En el próximo tema exploraremos el manejo de excepciones y errores, complementando nuestro conocimiento de estructura de código con técnicas de programación defensiva.

🏷️ Etiquetas:
python módulos paquetes programación ingeniería