📝 Repaso rápido: ¿Qué es la modularidad en Python?
La modularidad en Python permite dividir un programa en partes más pequeñas llamadas módulos, que son archivos con código independiente y reutilizable. Estos módulos pueden ser importados en diferentes aplicaciones, reduciendo la redundancia y facilitando el mantenimiento del código.
Es hora de aprender a trabajar aplicando modularidad en Python. Anteriormente vimos que Python es un lenguaje que permite trabajar con más de un paradigma (programación estructurada y orientada a objetos). Normalmente, cuando programamos un script sencillo aplicamos solo el paradigma de programación estructurada (secuencia, selección e iteración), y cuando necesitamos programar un proyecto un poco más complejo y queremos incluir los beneficios del paradigma orientado a objetos (reutilización de los componentes, facilidad de mantenimiento y modificación de objetos), utilizamos clases (POO). Pero hay aún una propiedad llamada modularidad en Python que corresponde al paradigma orientado a objetos que aún no hemos estudiado del todo, la cual nos brinda una serie de beneficios muy importantes.

🧩 ¿Qué es la modularidad en Python?

La modularidad es una propiedad que nos permitirá subdividir nuestro programa en partes más pequeñas (subprogramas) que habitualmente llamamos «módulos», los cuales deben ser independientes de la aplicación o programa original en sí.

Estos módulos son archivos que alojan código independiente con una determinada funcionalidad, y cuando hablamos de independencia nos referimos a que pueden ser reutilizados por otras aplicaciones y no dependen directamente de la aplicación original en la cual los utilizamos. Así, Python cuenta con diversos módulos que podemos «traer» a nuestro código y utilizarlos para facilitarnos y ahorrarnos programar código, entre otros beneficios que explicaremos al final del artículo.

modularidad en python numpy flask-minUn ejemplo claro es el módulo «math», que en su código incluye varias operaciones matemáticas que podemos llamar como una función luego de importar el módulo. Y no solo eso, podemos crear nuestros propios módulos para utilizarlos en nuestros proyectos cuando sea necesario. Así, por ejemplo, tú puedes crearte un módulo que muestre un menú en consola, y cuando necesites utilizarlo en un proyecto, simplemente lo importas y lo utilizas, variando en cada proyecto los ítems del mismo, pero sin necesidad de crear nuevamente todo el algoritmo y código que implica presentar ese menú.

Por ello, la modularidad en Python está ligada también a la funcionalidad (funciones). Así, utilizando todas estas propiedades del paradigma orientado a objetos, logramos reducir mucho la cantidad de líneas de código que debemos escribir y evitamos la redundancia de código (escribir varias veces el mismo código), como ya explicamos en funciones en Python.

👽 Ejemplo de modularidad en Python utilizando clases

Vamos a ver un ejemplo: supongamos que estamos programando una aplicación donde las personas deben elegir una opción y esta será almacenada en una variable para un futuro. Sabemos que siempre que programamos tenemos que recurrir a un menú de selección y presentarle al menos dos opciones al usuario, entonces ¿por qué no programar un módulo para ese menú y llamarlo directamente de la aplicación en la que lo necesitemos?. Y pues, como ya vimos clases y funciones, haremos uso de ello (porque debemos dejar atrás eso de programar sin usar clases si queremos avanzar como desarrolladores).

Pero antes de continuar con esta entrada, te recomiendo leer otra entrada que publiqué donde explico cómo crear e importar un módulo, sin usar clases, básico y sencillo para que lo entienda cualquiera aquí: Módulos y librerías en Python.

Luego de leer esa entrada sobre módulos y librerías, vuelve que aquí te espera otro ejemplo.

Aplicación básica usando clases y modularidad en Python de ejemplo:

Recordemos que ambos archivos, el de la aplicación y el módulo, deben estar en el mismo directorio o, en caso contrario, debemos especificarlo al momento de importarlo.

Primero debemos crear el módulo que se encargará de ser nuestro menú, pero recuerda que debe ser «reutilizable». Primordial cuando trabajamos con modularidad en Python es que nuestros módulos puedan ser utilizados desde otro programa o código fuente.

Así que debemos programarlo pensando en ello. En este caso, lo haremos con dos opciones para mantenerlo simple, pero en un caso real deberíamos contemplar pasar las opciones con **kwargs, utilizar try/except para manejar errores, entre otras cosas. Aquí lo mantengo básico para que no te pierdas entre código que no es importante para comprender el funcionamiento.

En fin, mi módulo «menu»:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# menu.py
# Copyright 2020 pyro 
# Módulo para presentar menús

def menu(opcion1, opcion2):
    """Función que presenta un menú con dos opciones y retorna la selección del usuario."""
    print("Menú:")
    print(f"1. {opcion1}")
    print(f"2. {opcion2}")
    while True:
        try:
            nsel = int(input("Ingresa un número de opción (1 o 2): "))
            if nsel in [1, 2]:
                print("¡Gracias!")
                return nsel
            else:
                print("Selecciona una opción válida (1 o 2).")
        except ValueError:
            print("Por favor, ingresa un número válido.")

Fíjate que el módulo intenta trabajar todo con parámetros, para luego pasarle los argumentos desde la aplicación en que se utilice. De lo contrario, nuestro módulo no sería reutilizable si yo colocara directamente en él, por ejemplo, «Opción 1: comprar la revista, opción 2: no comprar la revista». Claro, si luego quisiera utilizar este módulo en otra aplicación que no trate de revistas, debería modificarlo y entonces ya no podría utilizarlo en la primera aplicación y tendría que crear otro módulo más. ¿Me explico? La idea de la modularidad en Python es que el código sea reutilizable siempre para determinada función, en este caso, presentar un menú de opciones o, como en el ejemplo anterior que te pedí que leyeras, hacer cálculos matemáticos simples.

Ahora vamos a utilizar el módulo en una aplicación:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# persona.py
# Copyright 2020 pythones.net
# Aplicación de ejemplo: clases y modularidad

from menu import menu  # Importamos la función menu del módulo

class Persona:
    """Clase que representa a una persona con un nombre y capacidad de elegir una opción."""
    
    def __init__(self, nombre):
        self.nombre = nombre

    def elegir(self):
        print(f"Hola, {self.nombre}, es momento de elegir")
        # Llamamos la función menu y almacenamos su retorno
        nsel = menu("Comprar Revista", "No comprar")
        # Trabajamos con la elección
        if nsel == 1:
            print("Has elegido la opción 1: Comprar")
        else:
            print("Has elegido la opción 2: No comprar nada, ¡tacaño!")

# Instanciamos y ejecutamos
matias = Persona("Matías")
matias.elegir()

Entonces, aquí sí pasamos a la función los argumentos para sus parámetros, y hablamos de «comprar revistas» y demás, no en el módulo. Porque, si no, no sería reutilizable por otra aplicación.

Pues básicamente expliquemos ahora el funcionamiento: Nuestro módulo es algo así como una máquina que trabaja aparte de nuestra aplicación, recibiendo argumentos para sus parámetros y devolviéndonos un resultado. Fíjate que nuestra aplicación está programada utilizando POO y, en cambio, nuestro módulo es simplemente programación estructurada donde trabajamos con valores y selección (aunque también podemos trabajar con clases en módulos, en este ejemplo no lo hice para mantenerlo sencillo).

Nuestra aplicación se basa en un simple condicional según el valor de la variable «nsel», el cual otorga la función «menu» y, en base a ese valor que retorna la función, se bifurca en un print u otro.

Nuestra función menu, cuando es llamada, requiere que se le pasen ciertos argumentos (el texto de las opciones, «comprar o no revista» en este caso) y utiliza esos argumentos para brindar las opciones y se encarga de retornarnos el valor entero que elija para trabajar con él desde nuestra aplicación original.

👾 Aplicar el concepto de modularidad en Python

Al hablar de modularidad en Python, no solo hablamos de crear nuestros propios módulos o incluir los que necesitamos, sino que también hablamos de modificar nuestra forma de programar. A estas alturas, si me llevas leyendo, deberías poder recurrir a clases y modularidad en cada proyecto que encares, creando varios módulos. Al momento de estructurar tu programa, deberás recurrir a organizarlos en una o varias carpetas. Para ello, aprenderemos qué son los paquetes y librerías en Python.

🗃️ Paquetes en Python

Al tener un conjunto de módulos (independientes entre sí o no), podemos aún así relacionarlos y almacenarlos dentro de carpetas. Por ejemplo, podríamos tener un proyecto con tres módulos diferentes dentro de una misma carpeta, pero que se relacionan, es decir, necesitan uno de otro para poder funcionar y se conectan de alguna forma especificada por nosotros (interfaz). Esta carpeta podría convertirse en un paquete.

📦 ¿Qué es un paquete en programación modular?

Un paquete es un conjunto de módulos que pueden estar conectados entre sí o no mediante una interfaz definida por el programador y que tienen una finalidad específica dentro del programa que los utiliza.

Así, comprender estos conceptos de modularidad te permitirá organizar muchas líneas de código en diferentes módulos y paquetes e ir llamando y utilizándolos desde la aplicación principal.

📦 ¿Cómo creo mis propios paquetes en Python?

Crear un paquete no solo es ubicar los módulos dentro de una carpeta; estos módulos deben tener para ti una relación particular, de lo contrario, no sería necesario almacenarlos juntos en la misma ubicación. Es una buena práctica para el programador subdividir su programa en módulos, pero con la coherencia de crear paquetes solo de aquellos que se relacionan.

Para crear un paquete, debemos crear una carpeta en el directorio donde se encuentra nuestra aplicación y, dentro de esta, alojar un archivo «.py» llamado específicamente «__init__.py», lo que le indicará al intérprete que se trata de un directorio que contiene módulos (un paquete). En este caso, el módulo «menu» del ejemplo anterior lo he metido en la carpeta «menus», la cual será transformada en un paquete al añadir un archivo vacío llamado «__init__.py», quedando así:

📤 Importar módulos de paquetes

Ahora, al momento de ejecutar nuestro código como lo hicimos anteriormente, recibiremos un error, puesto que el módulo «menu» fue movido de la carpeta en donde se encontraba el código fuente desde el cual lo llamábamos.

Para localizar este módulo, debemos indicar el nombre del paquete al que pertenece y el nombre del mismo seguido de un punto, modificando el código fuente para que nos quede:

from menus.menu import menu

Y ahora sí:

Si tuviéramos dentro del paquete «menus» otro módulo, por ejemplo, «menumultiple», deberíamos importarlo en la siguiente línea:

from menus.menu import menu

from menus.menumultiple import onlymenu

Suponiendo que ese módulo «menumultiple» tuviera más de una función y yo no quisiera llamarlas todas porque dentro de «menumultiple» también hay una función que se llama «menu» y se crearía un conflicto. Entonces, importo únicamente la función que quiero, «onlymenu» (por ejemplo), de ese módulo del paquete. ¿Me entiendes? Así podemos importar una, varias o todas las funciones de diferentes módulos, evitando conflictos entre funciones.

⛴️ Importar paquetes de terceros en Python

Bueno, bueno, ya nos pusimos vagos. Es que es lo mejor de programar en Python, la vagancia, jaja. Podemos recurrir a innumerables paquetes y módulos, tanto de la librería estándar de Python como de paquetes desarrollados por terceros, miembros de diferentes comunidades orientadas a la programación.

Así, utilizar módulos de terceros nos quita un gran peso de encima de tener que «reprogramar lo ya programado» y, como buenos paisanos, debemos evitar la redundancia en este mundo, que ya hay demasiada. ¡El trabajo duro no es para los pythoner’s, ya lo digo yo!

Para importar un módulo o paquete de terceros, primero debemos ubicarlo, conocer qué es lo que hace y en qué nos va a servir. Donde habitualmente puedes encontrar muchos paquetes y módulos es en PyPI.org, además de su documentación, donde podrás comprender mejor la implementación del mismo.

Luego de encontrar el paquete que necesitas, para importarlo debes usar «pip», del cual ya hablamos anteriormente, y con un simple:

pip install nombredelpaquete

En la consola, se procederá a instalar el paquete y luego bastará con importarlo desde nuestro archivo o intérprete.

Bien, y eso es todo por ahora. Pronto añadiré más contenido a esta entrada sobre modularidad en python. Recuerda la importancia de aplicar estos conceptos cuando desarrolles aplicaciones.

¡Nos vemos por ahí!


📝 Resumen: Modularidad en Python
  • 🔹 La modularidad permite dividir programas en módulos reutilizables, reduciendo redundancia.
  • 🔹 Los paquetes son carpetas con módulos relacionados, marcados con un archivo __init__.py.
  • 🔹 Importa módulos con from paquete.modulo import funcion para evitar conflictos.
  • 🔹 Usa PyPI para encontrar e instalar paquetes de terceros con pip install.
¡Compartir es una forma de agradecer! :)

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio