Els mòduls contenen un conjunt de funcions, variables o classes per a poder-los usar en qualsevol programa.

Introducció

Un mòdul o module a Python és un fitxer .py que allotja un conjunt de funcions, variables o classes per a poder-los usar en qualsevol programa.

Els mòduls permeten reutilitzar codi a un grau més alt del que hem vist amb les classes i les funcions per tal d'organitzar-lo.

Creació d'un nou mòdul.

Crear els nostres propis mòduls és molt fàcil 😉

Per exemple, podem definir un mòdul noumodul1.py amb dues funcions suma() i resta().

noumodul.py

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

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

Un cop definit, aquest mòdul pot ser usat o importat en un altre fitxer, com mostrem a continuació, anomenat altrenoumodul.py Usant import podem importar tot el contingut.

altrenoumodul.py

import noumodul

print(noumodul.suma(4, 3))   # 7
print(noumodul.resta(10, 9)) # 1

També podem importar únicament els components que ens interessin com mostrem a continuació. Aquesta forma és més eficient, ja que evitem carregar codi que no necessitem.

from mimodulo import suma, resta

print(suma(4, 3))   # 7
print(resta(10, 9)) # 1

Canviant els Nom dels mòduls amb as

D'altra banda, és possible canviar el nom del mòdul usant la paraula reservada as. Imaginem que tenim un mòdul moduloconnombrelargo.py

# moduloconnombrelargo.py
hola = "hola"

Per assignar un nom més curt al mòdul ho farem de la següent manera

import moduloconnombrelargo as m
print(m.hola)

Organització de mòduls.

És possible i molt habitual accedir a mòduls ubicats en una subcarpeta per a separar encara millor el codi. Imaginem la següent estructura:

.
├── exempleX.py
├── carpetaX
│   └── modulX.py

On modulo.py conté el següent:

# modulX.py
def hola(nom = "a tothom!"):
	print(f"Hola {nom}")

Des del nostre exempleX.py, podem importar el mòdul modulX.py de la següent manera:

from carpetaX.modulo import *

print(hola())
# Hola a tothom!

Mòduls i Funció Main

Un problema molt recurrent és quan creem un mòdul amb una funció com al següent exemple, i afegim algunes sentències a executar.

modulB.py

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

c = suma(1, 2)
print("La suma es:", c)

Si en un altre mòdul importem el nostre modulB.py, tal com està el nostre codi el contingut s'executarà, i això pot no ser el que vulguem.

modulC.py

import modulB
# Sortida: La suma es: 3

Depenent de la situació, pot ser important especificar que només volem que s'executi el codi si el mòdul és el __main__.

Anem a veure-ho amb aquest exemple; remarcant els punts importants:

modulMainB.py

import modulB

def main():
    c = suma(5, 3)

if __name__ == "__main__":
    main()

if name == "main": Aquest bloc només s'executa si el programa s'executa com un script. Per exemple:

$ python modulMainB.py

Quan el fitxer s'importa com un mòdul, aquest bloc no s'executa.

Funció main(): Conté la lògica principal del programa, desglossada en subfuncions que es poden reutilitzar per separat.

Subfuncions: suma() és cridades des de main(), facilitant la lectura i manteniment del codi.

Activitats

Crea un mòdul anomenat epidemic_utils.py que tingui funcions d'utilitat per a calcular taxes epidemiològiques d'enfermetats.

Les 2 funcions que us demanem crear són:

Taxa d'incidència: mesura el nombre de casos nous d'una malaltia en una població específica durant un període de temps determinat.

Els paràmetres d'entrada que tenim són:

  • casos_nous
  • poblacio_total

Normalment, s'expressa per cada 1.000 o 100.000 persones. En aquest cas serà per cada 1000 persones.

Taxa de Mortalitat: Mesura el nombre de morts causades per una malaltia en una població durant un període determinat.

Els paràmetres d'entrada que tenim són:

  • numero_morts
  • casos_totals

S'expressa com un percentatge o per cada 1.000 persones. Per unificar les dues mesures serà per cada 1000 persones.

Fórmules

En segon lloc, has de crear un mòdul ( epidemic_tests.py) amb mètodes de test per a les dues funcions, aquest ha d'importar el mòdul epidemic_utils.py.

Si et fa falta, revisa com funcionen els tests en Python.

Per últim, crea un mòdul anomenat epidemic_main.py que contingui la funció main i a sota de tot el bloc de codi que permeti executar el mòdul com un script:

if __name__ == "__main__":
    main()

# epidemic_utils.py

def calcular_taxa_incidencia(casos_nous, poblacio_total):
    """
    Calcula la taxa d'incidència per cada 1000 persones.
    
    :param casos_nous: Nombre de casos nous.
    :param poblacio_total: Població total.
    :return: Taxa d'incidència.
    """
    if poblacio_total <= 0:
        raise ValueError("La població total ha de ser major que zero.")
    return (casos_nous / poblacio_total) * 1000


def calcular_taxa_mortalitat(morts, casos_totals):
    """
    Calcula la taxa de mortalitat per cada 1000 persones.
    
    :param morts: Nombre de morts.
    :param casos_totals: Nombre total de casos.
    :return: Taxa de mortalitat.
    """
    if casos_totals <= 0:
        raise ValueError("El nombre total de casos ha de ser major que zero.")
    return (morts / casos_totals) * 1000
# epidemic_tests.py
import pytest
from epidemic_utils import calcular_taxa_incidencia, calcular_taxa_mortalitat

def test_calcular_taxa_incidencia():
    assert calcular_taxa_incidencia(30, 20000) == 1.5
    assert calcular_taxa_incidencia(0, 10000) == 0.0
    with pytest.raises(ValueError):
        calcular_taxa_incidencia(10, 0)

def test_calcular_taxa_mortalitat():
    assert calcular_taxa_mortalitat(5, 100) == 50.0
    assert calcular_taxa_mortalitat(0, 1000) == 0.0
    with pytest.raises(ValueError):
        calcular_taxa_mortalitat(1, 0)

# Executa les proves si s'executa aquest fitxer directament
if __name__ == '__main__':
    pytest.main()
# epidemic_main.py

from epidemic_utils import calcular_taxa_incidencia, calcular_taxa_mortalitat

def main():
    # Exemple d'ús de les funcions
    poblacio = 20000
    casos_nous = 30
    morts = 5
    casos_totals = 100

    taxa_incidencia = calcular_taxa_incidencia(casos_nous, poblacio)
    taxa_mortalitat = calcular_taxa_mortalitat(morts, casos_totals)

    print(f"Taxa d'incidència: {taxa_incidencia} casos per 1.000 persones")
    print(f"Taxa de mortalitat: {taxa_mortalitat} morts per 1.000 persones")

if __name__ == "__main__":
    main()