Módulos
Contents
Módulos#
Importando módulos#
Las definiciones de funciones en Python en uno o más archivos separados para facilitar su manteniniento y para permitir usarlos en varios programas sin copiar las definiciones en cada uno.
Cada archivo que almacenda definciones de funciones se llama “módulo” y el nombre del módulo es igual al del archivo pero sin la extensión “.py”.
Las funciones almacenadas en un módulo están disponibles para un programa usando la palabra clave
import
seguida del nombre del módulo.Aunque no es esencial, se acostumbra poner las instrucciones
import
al inicio del programa.Las funciones importadas pueden usarse llamando su nombre como un “punto-sufijo” luego del nombre del módulo. Por ejemplo, una función
sqrt
de un módulo importadonumpy
puede llamarse connumpy.sqrt()
Algunos paquetes (módulos) muy útiles#
En nuestro curso, los siguientes paquetes (= colecciones de módulos) serán muy útiles
numpy
Paquete base para arreglos N-dimensional. Operaciones matemáticas, especialmente álgebra linealmatplotlib
gráficos 2Dpandas
estructuras para almacenar y analizar datosscipy
librería fundamental para computación científicabccr
ofrece funciones para descargar datos del Banco Central de Costa Ricamacrodemos
contiene demos de conceptos macroeconométricos, por ejemplo los modelos ARMAcompecon
Para resolver modelos de economía computacional
Algunos ejemplos:#
Para importar numpy
import numpy
numpy.sqrt(9)
3.0
Mismo ejemplo, pero dándolo un “alias” al módulo
import numpy as np
np.sqrt(9)
3.0
Mismo ejemplo, pero importando solo la función sqrt
from numpy import sqrt, cos, sin
sqrt(9)
3.0
¿Por qué trabajar con módulos?#
Una ventaja de organizar el código en módulos y paquetes es evitar desordenar el espacio de nombres.
Los módulos permites tener funciones del mismo nombre en espacios de nombre separados, obligándonos a ser explícitos acerca de cuál es la que usamos.
Por ejemplo, tanto math
como numpy
tienen una función cos
para computar el coseno, pero su implementación es muy distinta.
Con numpy
:#
\(\pi\)
π = np.pi
np.cos(π)
-1.0
import numpy as np
print(np.cos(0))
print(np.cos([0, 1, np.pi]))
1.0
[ 1. 0.54030231 -1. ]
Con math
:#
Esta celda da un error, porque la función math.cos
fue definida para calcular el coseno de un único número, no de una lista de números a la vez (como sí lo hace la función np.cos
)
import math
print(math.cos(0))
print(math.cos([0,1, np.pi]))
1.0
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_1036/1563810609.py in <module>
1 import math
2 print(math.cos(0))
----> 3 print(math.cos([0,1, np.pi]))
TypeError: must be real number, not list
Iteración más rápida#
nrep = 12_000
values = list(range(nrep))
%%timeit
option0 = np.empty_like(values)
for i, x in enumerate(values):
option0[i] = math.cos(x)
4.53 ms ± 59.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit
option1 = list()
for x in values:
option1.append(math.cos(x))
2.4 ms ± 25.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit
option2 = [math.cos(x) for x in values]
1.85 ms ± 19.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit
option3 = np.cos(values)
954 µs ± 8.72 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Ejemplo de módulo: Trabajando con decimales#
Los programas de cómputo que ejecutan aritmética con números de punto flotante pueden producir resultados inesperados e imprecisos porque los números de punto flotante no pueden representar adecuadamente todos los número decimales.
item, rate = 0.70, 1.05
tax = item * rate
total = item + tax
txt, val = ['item','tax','total'], [item,tax,total]
for tt, vv in zip(txt, val):
print(f'{tt:5s} = {vv:.2f}')
item = 0.70
tax = 0.73
total = 1.44
Con más decimales
for tt, vv in zip(txt, val):
print(f'{tt:8s} = {vv:.20f}')
item = 0.69999999999999995559
tax = 0.73499999999999998668
total = 1.43500000000000005329
Los errores de la aritmética de punto flotante pueden evitarse usando el módulo de Python decimal
. Este módulo contiene un objeto Decimal()
con el cual los números de punto flotante pueden representarse con más precisión.
from decimal import Decimal
item, rate = Decimal('0.70'), Decimal('1.05')
tax = item * rate
total = item + tax
txt, val = ['item','tax','total'], [item,tax,total]
for tt, vv in zip(txt, val):
print(f'{tt:5s} = {vv:.2f}')
item = 0.70
tax = 0.74
total = 1.44
Con más decimales
for tt, vv in zip(txt, val):
print(f'{tt:5s} = {vv:.20f}')
item = 0.70000000000000000000
tax = 0.73500000000000000000
total = 1.43500000000000000000
Creando un módulo#
Los módulo son muy convenientes para almacenar funciones relacionadas en un solo archivo, de manera que podamos mantener el orden en nuestro proyecto y además reutilizar esas funciones en distintos lugares.
Por ejemplo, archivo módulo_sencillo.py que está en la misma carpeta que este cuaderno de Jupyter contiene una función llamada hola
, con la saludamos. Además, hay una variable “string” llamada fecha
, donde guardé la fecha en que hice este módulo.
from módulo_sencillo import hola, fecha
Para crear un módulo, simplemente almacenamos una o más definiciones (de funciones, variables, clases) en un archivo con extensión .py. Si el archivo está en la misma carpeta que el archivo de Python en ejecución, lo podemos importar directamente.
hola()
Hola!! Soy la función `hola` del módulo `módulo_sencillo`
No hago más que saludar
fecha
'27 de marzo de 2022'
Otra manera es cargar el módulo completo, en cuyo caso
import módulo_sencillo
módulo_sencillo.hola()
Hola!! Soy la función `hola` del módulo `módulo_sencillo`
No hago más que saludar
módulo_sencillo.fecha
'27 de marzo de 2022'
Como no es práctico escribir módulo_sencillo
cada vez que usamos una de sus definiciones, le podemos poner un nombre más corto al importarlo, por ejemplo
import módulo_sencillo as ms
ms.hola()
Hola!! Soy la función `hola` del módulo `módulo_sencillo`
No hago más que saludar
ms.fecha
'27 de marzo de 2022'