Fundamentos de POO para interfaces gráficas en Python

Modularización del código

En las lecciones anteriores hemos visto que Python incluye un módulo llamado time para manipular la información del tiempo del sistema, pero no es el único.

Hay muchos otros módulos internos para realizar todo tipo de tareas y también contamos con un repositorio público llamado Python Package Index (PyPI.org) donde hay decenas de miles de módulos externos creados por la comunidad.

Un módulo es un fichero con definiciones de código que se puede importar en otros scripts y programas para utilizarlas. Si un programa cuenta con varios módulos que trabajan en conjunto para resolver un problema, a este conjunto de módulos se le denomina paquete, pero este concepto no lo trataré en el curso.

Por ejemplo supongamos que tenemos un módulo llamado operaciones.py con varias funciones para realizar operaciones aritméticas como sumas, restas y multiplicaciones.

operaciones.py

def suma(a, b):
	return a+b

def resta(a, b):
	return a-b

def producto(a, b):
	return a*b


# Funciones para probar el módulo
print("La suma de 5 y 10 es", suma(5, 10))
print("La resta de -9 y 8 es", resta(-9, 8))
print("El producto de 3 y -6 es", producto(3, -6))

Ahora supongamos que necesitamos usar alguna de estas operaciones en otro script llamado programa.py:

programa.py

import operaciones

print("4*6=", operaciones.producto(4, 6))

Al ejecutar el programa veremos que efectivamente se llama la función producto, pero antes se han ejecutado las pruebas del módulo, aquellas instrucciones que pusimos abajo.

Esto sucede porque import a parte de cargar las definiciones del módulo también ejecuta todas las instrucciones sueltas del fichero.

Para evitar este comportamiento hay que definir una condición en los módulos que ejecute sólo las instrucciones sueltas cuando se ejecuta específicamente el propio fichero. Eso se hace así:

# Funciones para probar el módulo
if __name__ == "__main__":
    print("La suma de 5 y 11 es", suma(5, 11))
    print("La resta de -9 y 8 es", resta(-9, 8))
    print("El producto de -3 y -6 es", producto(-3, -6))

La variable especial __name__ siempre contiene el nombre del propio fichero menos cuando concuerda con el script que ejecuta el programa, en ese caso su valor cambia a __main__, que en contexto indica que es el fichero "principal" del programa.

En otras palabras, al hacer:

python programa.py

El __name__ de operaciones.py es "operaciones" y no se ejecutan las instrucciones sueltas, pero si ejecutamos directamente:

python operaciones.py

Su __name__ cambia a __main__ y entonces sí se ejecutan.

Dejando esto de banda, también es posible especificar qué definiciones queremos importar:

from operaciones import producto, suma

print("4*6=", producto(4, 6))
print("5+3=", suma(5, 3))

Usando la importación específica no tenemos que llamar las funciones con el módulo delante, pero por contra no podremos usar las definiciones que no importamos, como resta.

Sea como sea con lo que hemos aprendido queda clara la idea de que los módulos nos permiten organizar el código de nuestros proyectos en diferentes ficheros para hacerlos más fáciles de mantener.

Como las bibliotecas gráficas están repletas de componentes y definiciones, conocer como trabajar con los módulos es un concepto esencial para utilizarlas.