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
- La filosofia de les "piles incloses"
math: matemàtiques més enllà dels operadorsrandom: atzar per a sortejos i dades de provadatetime: dates i hores de les comandesstringitextwrap: utilitats de textstatistics: estadística bàsica sense instal·lar ressysios: parlar amb el sistema- Mapa de la biblioteca estàndard en aquest curs
- Tancament del mòdul:
menu.pyreorganitzat
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.141592653589793Exemple 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 25A 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}") # 12Tres 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))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 medianaAmb 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")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 datetimei després fer servirdatetime.now():NameError/AttributeErroren confondre mòdul i classe. Oimport datetime+datetime.datetime.now(), ofrom datetime import datetime+datetime.now(). Tria un estil i sigues constant.- Esperar que
sys.argvporti nombres: tot arriba com a cadenes; converteix ambint()/float()com ambinput(). - Oblidar que
sys.argv[0]és l'script: el primer argument real éssys.argv[1], i cal comprovarlen(sys.argv)abans de fer-lo servir. - Anomenar fitxers com mòduls estàndard: un
random.pyostring.pyteu eclipsa l'oficial (lliçó 03-04). Els símptomes són errors absurds en mòduls "de tota la vida". - Fer servir
randomper a res seriós en seguretat: per a sortejos i proves és perfecte; per a contrasenyes o tokens existeix el mòdulsecrets. - 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)}") # 6Fixa'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
- Introducció a Python
- Configuració de l'Entorn de Desenvolupament
- Sintaxi de Python i Tipus de Dades Bàsics
- Variables i Constants
- Entrada i Sortida Bàsica
- Entorns Virtuals i Gestió de Paquets
Mòdul 2: Estructures de Control
Mòdul 3: Funcions i Mòduls
- Definició de Funcions
- Arguments de Funció
- Funcions Lambda
- Mòduls i Paquets
- Visió General de la Biblioteca Estàndard
Mòdul 4: Estructures de Dades
Mòdul 5: Programació Orientada a Objectes
Mòdul 6: Gestió de Fitxers
- Lectura i Escriptura de Fitxers
- Treball amb Fitxers CSV
- Gestió de Dades JSON
- Operacions amb Fitxers i Directoris
Mòdul 7: Gestió d'Errors i Excepcions
- Introducció a les Excepcions
- Gestió d'Excepcions
- Llançament d'Excepcions
- Excepcions Personalitzades
- Bones Pràctiques i Registre d'Errors amb logging
Mòdul 8: Temes Avançats
- Anotacions de Tipus (type hints)
- Decoradors
- Generadors
- Gestors de Context
- Concurrència: Fils i Processos
- Asyncio per a la Programació Asíncrona
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries amb unittest
- Proves amb pytest
- Desenvolupament Guiat per Proves
- Tècniques de Depuració
- Ús de pdb per a la Depuració
Mòdul 10: Desenvolupament Web amb Python
- Introducció al Desenvolupament Web
- Fonaments del Framework Flask
- Construcció d'APIs REST amb Flask
- Introducció a Django
- Construcció d'Aplicacions Web amb Django
Mòdul 11: Ciència de Dades amb Python
- Introducció a la Ciència de Dades
- NumPy per a la Computació Numèrica
- Pandas per a la Manipulació de Dades
- Matplotlib per a la Visualització de Dades
- Introducció a l'Aprenentatge Automàtic amb scikit-learn
