A la lliçó anterior vas aprendre a importar mòduls i en vas crear un de propi. Ara toca obrir el regal que ve amb cada instal·lació de Python: la biblioteca estàndard, més de dos-cents mòduls ja escrits, provats i documentats que cobreixen matemàtiques, atzar, dates, text, fitxers i molt més — sense instal·lar res, sense pip, sense .venv a tocar. Els pythonistes en diuen la filosofia de les "piles incloses" (batteries included): abans de programar res, pregunta't si la biblioteca estàndard ja ho porta. Aquesta lliçó és una visita guiada, no una enciclopèdia: veuràs els mòduls que més faràs servir amb exemples breus aplicats a Papyrus, i un mapa de quins reprendrem a fons a la resta del curs. Tancarem el mòdul amb la versió definitiva (per ara) de menu.py, reescrita sobre papyrus_utils.

Contingut

  1. La filosofia de les "piles incloses"
  2. math: matemàtiques més enllà dels operadors
  3. random: atzar per a sortejos i dades de prova
  4. datetime: dates i hores de les comandes
  5. string i textwrap: utilitats de text
  6. statistics: estadística bàsica sense instal·lar res
  7. sys i os: parlar amb el sistema
  8. Mapa de la biblioteca estàndard en aquest curs
  9. Tancament del mòdul: menu.py reorganitzat

La filosofia de les "piles incloses"

Tot el que vas veure a 03-04 s'aplica tal qual: import math funciona igual que import papyrus_utils, només que el fitxer viu a les carpetes de la biblioteca estàndard de sys.path en comptes de al teu projecte. La documentació oficial (docs.python.org, secció Library Reference) és la referència canònica; help(modul) al REPL és la drecera ràpida. L'habilitat a entrenar no és memoritzar funcions, sinó saber que el mòdul existeix: qui sap que statistics existeix no reimplementa la mitjana amb un bucle.

math: matemàtiques més enllà dels operadors

Els operadors (+, **, //...) cobreixen el bàsic; math aporta la resta:

import math

print(math.sqrt(16))        # 4.0  arrel quadrada
print(math.ceil(2.04))      # 3    arrodoniment SEMPRE cap amunt
print(math.floor(9.83))     # 9    arrodoniment SEMPRE cap avall
print(math.pi)              # 3.141592653589793

Exemple de botiga: els llibres arriben en caixes de 6 unitats. Si l'Anna necessita 20 exemplars, quantes caixes demana?

caixes = math.ceil(20 / 6)
print(f"Comanda: {caixes} caixes")   # 4 (amb 3.33 caixes no n'hi ha prou: s'arrodoneix cap amunt)

Compte amb el matís davant de round(), que ja coneixes: round(3.33) dona 3 (al més proper), math.ceil(3.33) dona 4 (sostre). Per a "quants contenidors necessito?", sempre ceil.

random: atzar per a sortejos i dades de prova

import random

print(random.randint(1, 6))            # enter entre 1 i 6, TOTS DOS inclosos
print(random.choice(cataleg))          # un element a l'atzar de la llista
print(random.sample(cataleg, 2))       # 2 elements diferents, sense repetir
print(round(random.uniform(5, 25), 2)) # float a l'atzar entre 5 i 25

A Papyrus, random.choice() resol la "recomanació sorpresa del dia", i random.sample() un sorteig entre socis sense repetir guanyador. El seu altre gran ús professional: generar dades de prova (preus, estocs) per assajar programes abans de tenir dades reals. I un truc de laboratori: random.seed(42) fixa la llavor del generador perquè la seqüència "aleatòria" sigui reproduïble — essencial per depurar i, més endavant, per a les proves del mòdul 9.

datetime: dates i hores de les comandes

El mòdul datetime conté (entre d'altres) les classes date i datetime — sí, mòdul i classe es diuen igual, origen de confusions eternes. L'habitual és importar les classes directament:

from datetime import date, datetime, timedelta

avui = date.today()
ara = datetime.now()
print(avui)                             # 2026-07-13
print(f"{ara:%d/%m/%Y %H:%M}")          # 13/07/2026 10:45  (format a mida)

# La comanda de "Faust" arriba en 7 dies:
arribada = avui + timedelta(days=7)
print(f"La comanda de Faust arribara el {arribada:%d/%m/%Y}")

# Quants dies fa que espera Lluis? (restar dates dona un timedelta)
encarrec = date(2026, 7, 1)
print(f"Dies d'espera: {(avui - encarrec).days}")    # 12

Tres idees clau: els objectes data s'operen (sumar un timedelta, restar dues dates), es formaten en f-strings amb codis %d, %m, %Y, %H, %M, i es construeixen amb date(any, mes, dia). Amb això Papyrus pot datar tiquets i calcular lliuraments; quan la botiga guardi comandes en fitxers (mòdul 6), les dates viatjaran com a text i datetime les interpretarà de tornada.

string i textwrap: utilitats de text

Dos mòduls petits però resultons. string ofereix constants llestes per validar:

import string

print(string.ascii_lowercase)   # abcdefghijklmnopqrstuvwxyz
print(string.digits)            # 0123456789
print(string.punctuation)       # !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

Per exemple, per comprovar que un codi de descompte només fa servir lletres majúscules i dígits: all(c in string.ascii_uppercase + string.digits for c in codi).

textwrap ajusta paràgrafs a una amplada donada — perfecte perquè la sinopsi d'un llibre càpiga al tiquet de 40 columnes de Papyrus:

import textwrap

sinopsi = ("Faust, savi insatisfet, pacta amb Mefistofil: "
           "joventut i coneixement a canvi de la seva anima.")
print(textwrap.fill(sinopsi, width=40))
Faust, savi insatisfet, pacta amb
Mefistofil: joventut i coneixement a
canvi de la seva anima.

statistics: estadística bàsica sense instal·lar res

Abans d'arribar a pandas (mòdul 11), l'estadística de cada dia ja ve inclosa:

import statistics

preus = [12.50, 9.95, 15.90, 21.00]
print(statistics.mean(preus))     # 14.8375  mitjana
print(statistics.median(preus))   # 14.2     mediana

Amb mean() l'Anna respon "quin és el preu mitjà del meu catàleg?" en una línia. La mediana resisteix millor els valors extrems: si hi entrés un facsímil de 300 €, la mitjana es dispararia i la mediana amb prou feines es mouria.

sys i os: parlar amb el sistema

De sys ja coneixes sys.path (lliçó 03-04). L'altra estrella seva és sys.argv: la llista d'arguments de línia d'ordres amb què s'ha executat l'script — l'equivalent per a scripts dels paràmetres d'una funció. sys.argv[0] és el nom del mateix script i la resta, el que s'ha escrit al darrere:

# consulta.py — us: python consulta.py <titol>
import sys

from papyrus_utils import cercar_llibre

cataleg = ["L'Odissea", "Hamlet", "El Quixot"]

if len(sys.argv) < 2:
    print("Us: python consulta.py <titol>")
else:
    index = cercar_llibre(cataleg, sys.argv[1])
    print("Al cataleg" if index is not None else "No disponible")
> python consulta.py Hamlet
Al cataleg

Així l'Anna consulta sense passar pel menú: scripts "d'un sol cop" per a tasques ràpides. Compte: els arguments arriben sempre com a cadenes, igual que amb input().

Per la seva banda, os (i el seu modern company pathlib) es comunica amb el sistema operatiu: os.getcwd() diu a quina carpeta ets, os.listdir() llista fitxers, i d'aquí endavant — crear carpetes, comprovar si un fitxer existeix, esborrar. Només te'l presento: és protagonista del mòdul 6, quan el catàleg visqui en fitxers.

Mapa de la biblioteca estàndard en aquest curs

Mòdul Per a què serveix On es fa servir en aquest curs
math Arrels, sostres/terres, constants Des d'ara, on calgui
random Atzar, mostreig, dades de prova Aquí; dades d'exemple als mòduls 4-6
datetime Dates, hores, aritmètica temporal Aquí; dates de comandes al mòdul 6 (CSV/JSON)
string / textwrap Constants de text / paràgrafs a mida Curiositats útils; cadenes a fons a 04-05
statistics Mitjana, mediana i companyia Aquí; avantsala de pandas (mòdul 11)
sys argv, path, sortida de l'intèrpret Aquí i en depuració (mòdul 9)
os / pathlib Fitxers, carpetes, rutes Mòdul 6
collections Estructures de dades extra Mòdul 4 (04-06)
csv / json Llegir i escriure dades estructurades Mòdul 6
logging Registre professional d'esdeveniments Mòdul 7
unittest / pdb Proves i depuració Mòdul 9
asyncio / threading Concurrència Mòdul 8

Guarda aquesta taula com a brúixola: gran part del temari que et queda és, en el fons, aprendre a fer servir bé la biblioteca estàndard.

Tancament del mòdul: menu.py reorganitzat

La promesa del mòdul 2 queda saldada. La versió final de menu.py importa papyrus_utils (lliçó 03-04), reparteix la feina en funcions amb una responsabilitat cadascuna (03-01), fa servir arguments keyword (03-02) i fins i tot data la sessió amb datetime:

"""Menu de gestio de la llibreria Papyrus."""

from datetime import date

from papyrus_utils import NOM_BOTIGA, cercar_llibre, preu_final

cataleg = ["L'Odissea", "Hamlet", "El Quixot"]
preus = [12.50, 9.95, 15.90]
estocs = [4, 6, 8]


def mostrar_cataleg():
    """Imprimeix la taula de titols, preus i estoc."""
    print(f"\n{'Titol':<12} {'Preu':>8} {'Estoc':>6}")
    print("-" * 28)
    for titol, preu, estoc in zip(cataleg, preus, estocs):
        print(f"{titol:<12} {preu:>6.2f} € {estoc:>6}")


def consultar_llibre():
    """Demana un titol i en mostra la fitxa, amb el preu de soci inclos."""
    cercat = input("Titol a cercar: ")
    if not cercat:
        print("No has escrit res.")
        return
    index = cercar_llibre(cataleg, cercat)
    if index is None:
        print(f"'{cercat}' no es al cataleg.")
        return
    base = preus[index]
    print(f"'{cataleg[index]}': {base:.2f} € "
          f"(socis: {preu_final(base, soci=True):.2f} €), estoc {estocs[index]}.")


def executar_menu():
    """Bucle principal del menu de la botiga."""
    print(f"Gestio de {NOM_BOTIGA} — {date.today():%d/%m/%Y}")
    while True:
        print("\n1. Veure cataleg\n2. Cercar un llibre\n3. Sortir")
        match input("Tria una opcio (1-3): "):
            case "1":
                mostrar_cataleg()
            case "2":
                consultar_llibre()
            case "3":
                print(f"Tancant {NOM_BOTIGA}. Fins dema, Anna!")
                break
            case _:
                print("Opcio no valida. Tria 1, 2 o 3.")


if __name__ == "__main__":
    executar_menu()

Compara'l amb la versió monolítica del mòdul 2: fa el mateix i alguna cosa més (data, preu de soci a la fitxa), però ara cada peça té nom, docstring i lloc. consultar_llibre() fa servir return com a guarda — les seves sortides primerenques substitueixen el continue de la versió antiga. La lògica de negoci viu a papyrus_utils (reutilitzable des de tiquet.py o venda_soci.py), la presentació viu aquí, i el bloc __main__ permet que un altre script faci from menu import mostrar_cataleg sense engegar el menú sencer. Això ja no és un script: és un programa petit ben organitzat.

Errors Comuns i Consells

  • Reinventar la roda: escriure la teva pròpia mitjana, el teu propi barreig o el teu propi ajust de línies. Abans de programar una utilitat "genèrica", busca a la documentació: probablement ja existeix, sense errors i més ràpida.
  • import datetime i després fer servir datetime.now(): NameError/AttributeError en confondre mòdul i classe. O import datetime + datetime.datetime.now(), o from datetime import datetime + datetime.now(). Tria un estil i sigues constant.
  • Esperar que sys.argv porti nombres: tot arriba com a cadenes; converteix amb int()/float() com amb input().
  • Oblidar que sys.argv[0] és l'script: el primer argument real és sys.argv[1], i cal comprovar len(sys.argv) abans de fer-lo servir.
  • Anomenar fitxers com mòduls estàndard: un random.py o string.py teu eclipsa l'oficial (lliçó 03-04). Els símptomes són errors absurds en mòduls "de tota la vida".
  • Fer servir random per a res seriós en seguretat: per a sortejos i proves és perfecte; per a contrasenyes o tokens existeix el mòdul secrets.
  • Consell: dedica cinc minuts a fullejar l'índex de la Library Reference oficial. No per aprendre-te'l, sinó perquè "em sona que hi ha un mòdul per a això" es converteixi en el teu primer reflex.

Exercicis

Exercici 1: sorteig del club de lectura

Escriu sorteig.py: donada socis = ["Lluis", "Marta", "Chen", "Aitana", "Pau"], tria amb random.sample() dos guanyadors diferents d'un exemplar de "Faust" i imprimeix cadascun amb la data límit de recollida: avui més 15 dies, formatada dd/mm/aaaa (fes servir date.today() i timedelta).

Exercici 2: informe exprés del catàleg

Escriu informe.py que, amb preus = [12.50, 9.95, 15.90, 21.00], imprimeixi: el preu mitjà i la mediana (mòdul statistics, tots dos amb :.2f), el preu més alt i el més baix (funcions integrades max()/min()), i quantes caixes de 6 unitats necessita l'Anna per guardar 31 llibres (mòdul math). Remata-ho amb una línia separadora de guions generada amb "-" * 30.

Exercici 3: consulta amb arguments i papyrus_utils

Amplia el consulta.py d'aquesta lliçó: ha d'acceptar python consulta.py <titol> [soci]. Si el títol existeix al catàleg, imprimeix el seu preu final — de soci si el segon argument és exactament soci, normal en cas contrari — fent servir preu_final() de papyrus_utils. Si no existeix o falta el títol, imprimeix l'avís corresponent. Prova-ho amb python consulta.py Hamlet soci (ha de donar 9.83 €).

Solucions

Exercici 1:

import random
from datetime import date, timedelta

socis = ["Lluis", "Marta", "Chen", "Aitana", "Pau"]
guanyadors = random.sample(socis, 2)
limit = date.today() + timedelta(days=15)

for nom in guanyadors:
    print(f"{nom}: recull el teu 'Faust' abans del {limit:%d/%m/%Y}")

sample() garanteix dos noms diferents (amb choice() dues vegades, en Lluís podria guanyar tots dos exemplars). La data es calcula una vegada i es reutilitza.

Exercici 2:

import math
import statistics

preus = [12.50, 9.95, 15.90, 21.00]

print(f"Preu mitja:     {statistics.mean(preus):.2f} €")   # 14.84 €
print(f"Mediana:        {statistics.median(preus):.2f} €") # 14.20 €
print(f"Mes car:        {max(preus):.2f} €")               # 21.00 €
print(f"Mes barat:      {min(preus):.2f} €")               # 9.95 €
print("-" * 30)
print(f"Caixes per a 31 llibres: {math.ceil(31 / 6)}")     # 6

Fixa't en la barreja natural de funcions integrades (max, min) i mòduls (statistics, math): la biblioteca estàndard comença on les integrades acaben.

Exercici 3:

import sys

from papyrus_utils import cercar_llibre, preu_final

cataleg = ["L'Odissea", "Hamlet", "El Quixot"]
preus = [12.50, 9.95, 15.90]

if len(sys.argv) < 2:
    print("Us: python consulta.py <titol> [soci]")
else:
    index = cercar_llibre(cataleg, sys.argv[1])
    if index is None:
        print(f"'{sys.argv[1]}' no es al cataleg.")
    else:
        es_soci = len(sys.argv) > 2 and sys.argv[2] == "soci"
        print(f"{cataleg[index]}: {preu_final(preus[index], soci=es_soci):.2f} €")

es_soci aprofita el curtcircuit de l'and: si no hi ha tercer argument, no intenta llegir sys.argv[2] (evitant un IndexError). Nota els imports en dos blocs PEP 8: estàndard (sys) a dalt, propis (papyrus_utils) a sota.

Conclusió

El mòdul 3 tanca el cercle que va obrir: el codi de Papyrus ja no viu dispers. Saps definir funcions amb def, docstring i return (03-01); dissenyar les seves signatures amb arguments posicionals, keyword, valors per defecte, *args/**kwargs i recórrer llistes paral·leles amb zip() (03-02); escriure lambdes d'usar i llençar com a criteri de sorted(), min() i max() (03-03); repartir el codi en mòduls propis com papyrus_utils.py amb if __name__ == "__main__" i paquets amb __init__.py (03-04); i orientar-te per la biblioteca estàndard amb math, random, datetime, statistics o sys.argv (03-05). El nou menu.py — funcions petites, negoci importat, presentació separada — és la prova de maduresa. Però queda una esquerda a la vista: el catàleg són tres llistes paral·leles que cal mantenir sincronitzades a mà, i ja ens ha obligat a fer malabars amb zip() i índexs. El mòdul 4 ataca just aquí: les estructures de dades de Python — llistes a fons, tuples, diccionaris, conjunts i les joies de collections — amb les quals cada llibre de Papyrus serà per fi una sola peça d'informació, i no un número de fila repartit en tres llistes.

Curs de Programació en Python

Mòdul 1: Introducció a Python

Mòdul 2: Estructures de Control

Mòdul 3: Funcions i Mòduls

Mòdul 4: Estructures de Dades

Mòdul 5: Programació Orientada a Objectes

Mòdul 6: Gestió de Fitxers

Mòdul 7: Gestió d'Errors i Excepcions

Mòdul 8: Temes Avançats

Mòdul 9: Proves i Depuració

Mòdul 10: Desenvolupament Web amb Python

Mòdul 11: Ciència de Dades amb Python

Mòdul 12: Projecte Final

© Copyright 2026. Tots els drets reservats