Modularidad en Python

 

modularidad en pythonEs hora de aprender a trabajar aplicando modularidad en python. Anteriormente vimos que python es un lenguaje que permite trabajar 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, el cual nos brinda una serie de beneficios muy importantes.

 

¿Qué es la modularidad en python?

modularidad en pythonLa modularidad es una propiedad que nos permitirá subdividir nuestro programa en partes más pequeñas (sub-programas) que habitualmente llamamos “módulos” las 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 lo utilizamos. Así python cuenta con diversos módulos que podemos “traer” a nuestro código y utilizarlo para facilitarnos y ahorrarnos programar código entre otros beneficios que explayaremos al final del artículo.

Un ejemplo claro es el módulo “math” por ejemplo 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 tu 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 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 publique donde explico como crear e importar un módulo, sin usar clases, básico y sencillito para que le entienda cualquiera aquí:

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 menu, 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, pero en este caso solo lo haremos con dos opciones, si fuera un caso real deberíamos contemplar pasar las opciones con “**args”, utilizar Try/except entre otras cosas, yo trato de mantenerlo “básico” para que no te pierdas entre código que no es importante para comprender el funcionamiento. Tu programa bien carajo!.

En fin mi módulo “menu“:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  menu.py
#  
#  Copyright 2020 pyro <pythones.net>
#  Módulo para presentar menus

def menu(a, b): #Creamos la función menu (3 parámetros)
    print ("Menu:") #Imprimimos las opciones (parámetros a y b)
    print(a)
    print(b)
    r = True
    while (r == True): #Iniciamos un bucle siempre que "r" sea true
        #Solicitamos una entrada entero
        
        nsel = int(input("Ingresa un número de opción:"))
        
        #Ahora evaluamos esa entrada almacenada en "nsel"
        
        if (nsel == 1): #Condicional = Si indica 1
            print ("Gracias!")
            return nsel #RETORNAMOS el valor de la variable
            r = False #Rompemos el bucle porque ya eligió
            
        elif (nsel == 2): #Condicional = Si indica 2
            print ("gracias!")
            return nsel #RETORNAMOS el valor de la variable
            r = False #Rompemos el bucle porque eligió
        
        else:
            print ("Selecciona una opción válida")
            
            """Al no elegir o colocar otro número
            no rompemos el bucle por lo que vuelve a
            solicitar entrada"""

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 colocará 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é de modificarlo y pues ahí ya no puedo utilizarlo en la primera aplicación y debería 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 el 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 pyro <pythones.net>
#  Aplicación de ejemplo clases y modularidad

from menu import * #Importamos nuestro módulo (IMPORTANTE NO OLVIDAR)

class persona (object): #Creamos una clase Persona
    
    def __init__(self, nombre): #Constructor y atributos
        self.nombre = nombre #Definimos valor del atributo
        
    def elegir (self): #Creamos el método elegir
        nsel = 0 #Variable nsel seteada en "0"
        print ("Hola", self.nombre, "es momento de elegir")
        
        #Llamamos la función menu y almacenamos su retorno en "nsel"
        nsel = menu("Opción1 = Comprar Revista","Opción2 = No comprar")
        
        #Y ahora trabajamos con esa elección
        if (nsel == 1):
            print("Has elegido la opción 1: Comprar")
        else:
            print("Has elegido la opcion 2: No comprar nada, tacaño!")
            

Matias = persona("Matias") #Instancia
Matias.elegir() #Llamamos el método elegir de la clase persona

Entonces aquí si, pasamos a la función los argumentos para sus parametros, y hablamos de “comprar revistas” y demás, no en el jodido módulo he!. Porque luego no será 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 devolviendonos un resultado. Fijate 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 brindarles 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

programación modular pythonAl 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 3 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.

Modularidad en python

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 especificamente “__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í:

Paquetes en python

 

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:

Módulos y paquetes en Python

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 *

Y ahora si:

Ejemplo módulos en python

Recordemos que el asterisco es un comodín que implica importar todas las funciones declaradas como explícitas del módulo. 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 *

from menus.menumultiple import onlymenu

Suponiendo 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 mendez?. 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 que 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, lo que 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, recuerda la importancia de aplicar estos conceptos cuando desarrolles aplicaciones!

Nos vemos por ahí!

 

 

 

Compartir es agradecer! :)