Les dues lliçons anteriors van deixar un problema molt concret sobre la taula. La llista va resoldre el «moltes tasques», però per guardar els camps de cada tasca ens va obligar a mantenir cinc llistes paral·leles sincronitzades a mà: un pop oblidat i el llistat comença a mentir. El motiu de fons és que en una llista les dades s'identifiquen per posició, i la posició no significa res: tasca[1] no diu si l'1 és el responsable o la prioritat.
Aquesta lliçó presenta dues estructures que resolen problemes diferents i que gairebé sempre s'ensenyen juntes. El diccionari guarda cada dada amb el seu nom, de manera que tasca["responsable"] s'explica sola. El conjunt guarda elements únics sense ordre, i és l'eina correcta per a preguntes del tipus «hi és, això?» o «quines etiquetes diferents fem servir?». Al final, TascaFàcil farà el salt a la v0.9 i una tasca passarà a ser, per fi, una sola cosa.
Contingut
- Clau i valor: el problema que resol el diccionari
- Crear diccionaris i accedir als seus valors
- Afegir, modificar i esborrar
- Recórrer un diccionari
update,setdefaulti què pot ser una clau- Diccionari per comprensió i recompte de freqüències
- Conjunts: elements únics i sense ordre
- Operacions entre conjunts
- Usos típics dels conjunts
- Llista, diccionari o conjunt: taula de decisió
- TascaFàcil v0.9: la tasca és un diccionari
- Errors comuns i consells
- Exercicis
- Conclusió
- Clau i valor: el problema que resol el diccionari
Un diccionari (tipus dict) és una col·lecció de parells clau → valor. La clau substitueix l'índex numèric: en comptes de recordar que el responsable és a la posició 1, el demanes pel seu nom.
tasca = {"titol": "Cartell fira del llibre", "responsable": "Marta",
"prioritat": "alta", "dies": 3, "completada": False}
print(tasca["responsable"]) # Marta
print(len(tasca)) # 5 -> nombre de parellsCompara les dues maneres de guardar la mateixa tasca:
| Llista | Diccionari | |
|---|---|---|
| S'hi accedeix per | Posició: tasca[1] |
Nom: tasca["responsable"] |
| Es llegeix sol | No: cal recordar l'ordre | Sí |
| Afegir un camp nou | Trenca tots els índexs posteriors | Només afegeix una clau |
| Ordre dels elements | Significatiu | Irrellevant per a l'accés |
| Bon ús | Moltes coses del mateix tipus | Els camps diferents d'una cosa |
Aquesta última fila és la regla de decisió: llista per a «molts», diccionari per a «un amb diversos camps». Els responsables de l'estudi són una llista (["Marta", "Luis", "Nuria"]); una tasca concreta és un diccionari. I quan vulguis moltes tasques, serà una llista de diccionaris, que és exactament 05-04.
- Crear diccionaris i accedir als seus valors
Hi ha dues maneres de crear-lo, i un diccionari buit s'escriu {}:
tasca = {"titol": "Menu Sole", "dies": 5} # literal amb claus
altra = dict(titol="Menu Sole", dies=5) # amb dict() i arguments per nom
buit = {}
print(tasca == altra) # True -> son equivalents
print(tasca["titol"]) # Menu Sole
print(tasca["responsable"]) # KeyError: 'responsable'
print(tasca.get("responsable")) # None -> no falla
print(tasca.get("responsable", "sense assignar")) # sense assignarPer llegir un valor hi ha, per tant, dos camins, i triar bé és important:
| Forma | Si la clau existeix | Si no existeix |
|---|---|---|
d[clau] |
Retorna el valor | KeyError i el programa s'atura |
d.get(clau) |
Retorna el valor | Retorna None |
d.get(clau, defecte) |
Retorna el valor | Retorna defecte |
La regla pràctica: fes servir d[clau] quan la clau ha de ser-hi (si no hi és, és un error de programació i vols assabentar-te'n), i .get() quan la seva absència sigui una possibilitat normal. Per comprovar-ho explícitament hi ha l'operador in, que en un diccionari mira les claus i no els valors: "titol" in tasca és True, però "Menu Sole" in tasca és False perquè això és un valor.
- Afegir, modificar i esborrar
Afegir i modificar s'escriuen igual, i aquest és un dels paranys del tipus: si la clau no existeix, es crea; si existeix, se sobreescriu sense avisar.
tasca = {"titol": "Menu Sole", "dies": 5}
tasca["responsable"] = "Luis" # la clau no existeix: s'afegeix
tasca["dies"] = 6 # la clau existeix: se sobreescriu
del tasca["dies"] # esborra; KeyError si no existeix
valor = tasca.pop("responsable") # esborra i retorna el valor
altre = tasca.pop("client", "cap") # amb defecte: no falla si no hi es
tasca.clear() # deixa el diccionari buitdel és la manera directa d'esborrar; .pop(clau) és la que fas servir quan a més necessites el valor que en surt, igual que a les llistes. I com a les llistes, el diccionari és mutable: si el passes a una funció i aquesta el modifica, el canvi es veu fora. Això és el que permetrà que canviar_prioritat(tasca) funcioni sense retornar res.
- Recórrer un diccionari
Un for directe sobre un diccionari recorre les claus. Els tres mètodes de vista permeten triar què vols recórrer:
| Mètode | Produeix a cada volta |
|---|---|
.keys() |
Les claus (és el mateix que el for directe) |
.values() |
Els valors |
.items() |
Parells (clau, valor) |
tasca = {"titol": "Cartell fira", "responsable": "Marta", "dies": 3}
for clau in tasca: # equival a tasca.keys()
print(clau, end=" ") # titol responsable dies
for valor in tasca.values():
print(valor, end=" ") # Cartell fira Marta 3
for clau, valor in tasca.items():
print(f"{clau:<12}: {valor}")
for clau, valor in sorted(tasca.items()): # recorregut alfabetic per clau
print(clau, valor).items() és el que faràs servir el 90 % de les vegades, perquè gairebé sempre necessites les dues coses alhora. Fixa't que el desempaquetatge for clau, valor in ... és el mateix mecanisme que ja vas veure amb enumerate i zip a 05-01. Des de Python 3.7 el diccionari conserva l'ordre d'inserció en recórrer-lo, però no t'hi recolzis per donar significat a les posicions: si necessites un ordre concret, demana'l explícitament amb sorted(), com a l'última línia.
update, setdefault i què pot ser una clau
update, setdefault i què pot ser una clau.update(altre) fusiona un altre diccionari dins del primer: afegeix les claus noves i sobreescriu les que coincideixin. És la manera neta d'aplicar diversos canvis de cop.
.setdefault(clau, valor) retorna el valor de la clau si existeix i, si no, la crea amb el valor indicat: serveix per garantir que una clau hi és sense esclafar el que ja hi hagués. I sobre les claus hi ha una regla estricta: una clau ha de ser immutable. Valen cadenes, números, booleans i tuples (05-04); no val una llista ni un altre diccionari.
tasca = {"titol": "Cartell fira", "dies": 3}
tasca.update({"dies": 4, "prioritat": "alta"}) # fusiona: dies passa a 4
tasca.setdefault("completada", False) # no hi era: la crea en False
tasca.setdefault("dies", 99) # ja hi era: no toca res, retorna 4
valid = {"marta": 3, 2026: "any", (1, 2): "coordenada"}
no_valid = {["marta"]: 3} # TypeError: unhashable type: 'list'El motiu, sense entrar en detalls: el diccionari col·loca cada valor en un lloc calculat a partir de la clau, així que si la clau pogués canviar després, el valor quedaria perdut en un lloc equivocat. Els valors, en canvi, poden ser el que vulguis: llistes, altres diccionaris, funcions. I les claus són úniques: escriure dues vegades la mateixa en un literal deixa només l'última.
- Diccionari per comprensió i recompte de freqüències
Igual que les llistes, els diccionaris admeten comprensió, amb la mateixa sintaxi més el parell clau: valor:
dies_per_tasca = {"Cartell fira": 3, "Menu Sole": 5, "Logotip Vidal": 2}
en_hores = {t: d * 8 for t, d in dies_per_tasca.items()}
print(en_hores) # {'Cartell fira': 24, 'Menu Sole': 40, 'Logotip Vidal': 16}
llargues = {t: d for t, d in dies_per_tasca.items() if d > 2}
print(llargues) # {'Cartell fira': 3, 'Menu Sole': 5}I ara un patró clàssic que apareix en tots els programes del món: comptar freqüències. La idea és fer servir el diccionari com a marcador, amb l'element de clau i el recompte de valor.
responsables = ["Marta", "Luis", "Marta", "Nuria", "Marta", "Luis"]
recompte = {}
for nom in responsables:
recompte[nom] = recompte.get(nom, 0) + 1
print(recompte) # {'Marta': 3, 'Luis': 2, 'Nuria': 1}
print(max(recompte, key=recompte.get)) # Marta -> qui te mes tasques
print(sorted(recompte.items(), key=lambda p: p[1], reverse=True))
# [('Marta', 3), ('Luis', 2), ('Nuria', 1)]La línia decisiva és recompte[nom] = recompte.get(nom, 0) + 1, i mereix llegir-se a poc a poc. recompte.get(nom, 0) retorna el recompte actual o 0 si és la primera vegada que apareix aquest nom; se li suma 1 i es desa. Aquest 0 per defecte és el que evita el KeyError de la primera volta i estalvia un if nom in recompte:. Després, max(recompte, key=recompte.get) recorre les claus i les compara pel seu valor —el key de 04-05 aplicat a un diccionari— i sorted(...) ordena els parells pel segon element; com ordena per dins continua sent matèria d'Algorismes d'ordenació.
- Conjunts: elements únics i sense ordre
Un conjunt (set) és una col·lecció d'elements únics i sense ordre. No hi ha índexs: conjunt[0] dóna error. A canvi, respon la pregunta «hi és, això?» de manera immediata i elimina duplicats sense esforç.
etiquetes = {"disseny", "impremta", "client", "disseny"}
print(etiquetes) # {'client', 'disseny', 'impremta'} -> el duplicat desapareix
print(len(etiquetes), "impremta" in etiquetes) # 3 True
buit_dict = {} # compte: aixo es un dict
buit_set = set() # el conjunt buit s'escriu aixi
des_de_llista = set(["Marta", "Luis", "Marta"]) # {'Marta', 'Luis'}L'ordre en què s'imprimeix no és el d'escriptura i no hi has de comptar. I compte amb el parany de la creació que mostren les tres últimes línies: {} no és un conjunt buit, sinó un diccionari buit. Els mètodes bàsics són quatre, i la diferència entre els dos d'esborrat és la de sempre:
| Mètode | Què fa | Si l'element no hi és |
|---|---|---|
.add(x) |
Afegeix x (si ja hi era, no passa res) |
— |
.discard(x) |
El treu | No fa res |
.remove(x) |
El treu | KeyError |
.pop() |
Treu un element qualsevol | KeyError si està buit |
Existeix també frozenset, la versió immutable del conjunt: un cop creat no admet add ni remove, i la seva utilitat principal és poder fer-se servir com a clau de diccionari, cosa que un set normal no pot.
- Operacions entre conjunts
Aquí és on els conjunts brillen: implementen directament les operacions de la teoria de conjunts, amb operadors d'una sola lletra.
Partim de marta = {"cartell", "menu", "logotip"} i luis = {"menu", "flyer"}.
| Operació | Operador | Mètode | Resultat | Significa |
|---|---|---|---|---|
| Unió | marta | luis |
.union() |
{'cartell','menu','logotip','flyer'} |
En un o en un altre |
| Intersecció | marta & luis |
.intersection() |
{'menu'} |
En tots dos |
| Diferència | marta - luis |
.difference() |
{'cartell','logotip'} |
Al primer i no al segon |
| Diferència simètrica | marta ^ luis |
.symmetric_difference() |
{'cartell','logotip','flyer'} |
En un però no en tots dos |
graph LR
A["Nomes MARTA<br/>cartell, logotip"] --- C["COMU<br/>menu"]
C --- D["Nomes LUIS<br/>flyer"]
El diagrama es llegeix així: menu és a la zona comuna (la intersecció), cartell i logotip són exclusius de la Marta (la diferència marta - luis) i flyer ho és del Luis. La unió són els quatre; la diferència simètrica, els tres de fora del centre. Existeix a més luis <= marta, que comprova si un conjunt està contingut en un altre (aquí, False), i >= per al contrari: són útils per validar coses com «són totes les prioritats introduïdes de les admeses?».
- Usos típics dels conjunts
Dos usos cobreixen gairebé tots els casos reals. El primer, eliminar duplicats d'una llista en una línia: amb responsables = ["Marta", "Luis", "Marta", "Nuria", "Luis"], l'expressió sorted(set(responsables)) retorna ['Luis', 'Marta', 'Nuria']. Fixa't en el sorted(): convertir a conjunt perd l'ordre original, així que si l'ordre importa cal reordenar després (o fer servir una altra tècnica). El segon ús és comprovar pertinença en col·leccions grans: preguntar x in conjunt és moltíssim més ràpid que x in llista quan hi ha milers d'elements, perquè el conjunt no recorre res. El perquè exacte s'estudia a Algorismes de cerca i Eficiència i notació Big-O; de moment queda't amb la conseqüència pràctica: si el teu programa fa moltes comprovacions de pertinença sobre una col·lecció sense duplicats, aquesta col·lecció hauria de ser un conjunt.
- Llista, diccionari o conjunt: taula de decisió
| Criteri | Llista | Diccionari | Conjunt |
|---|---|---|---|
| Sintaxi | [1, 2] |
{"a": 1} |
{1, 2} |
| S'hi accedeix per | Índex | Clau | No s'hi accedeix: es pregunta amb in |
| Manté l'ordre? | Sí, i significa alguna cosa | Sí, d'inserció | No |
| Admet duplicats? | Sí | Claus no, valors sí | No |
| Buscar un element | Recorre | Directe | Directe |
| Cas típic | Moltes coses iguals | Els camps d'una cosa | Etiquetes, pertinença, desduplicar |
Les preguntes que porten a la resposta correcta: importa l'ordre o els recorreré en seqüència? Llista. Cada dada té un nom propi? Diccionari. Només m'importa si una cosa hi és o no, i no vull repetits? Conjunt.
- TascaFàcil v0.9: la tasca és un diccionari
A la v0.8 vam aconseguir moltes tasques a costa de cinc llistes paral·leles fràgils. Ara arreglarem l'altra meitat del problema —la forma d'una tasca— i per veure-ho amb claredat tornem temporalment a gestionar-ne una de sola: a la v0.9 la tasca és un diccionari, i a 05-04 ajuntarem les dues idees en una llista de diccionaris.
# tascafacil.py - Estudi Alba / Versio 0.9: cada tasca es un diccionari
AMPLE = 46
PRIORITATS = ("alta", "mitjana", "baixa")
EQUIP = ("marta", "luis", "nuria")
OPCIONS = ("1", "2", "3", "4", "5")
ETIQUETES = {"disseny", "impremta", "client"}
# --- Entrada i logica sense canvis: demanar_text, demanar_opcio, demanar_enter,
# confirmar, classificar_urgencia, mostrar_menu, pausar ---
def registrar_tasca():
"""Demana les dades d'una tasca i retorna el diccionari complet."""
return {
"titol": demanar_text("Titol : "),
"responsable": demanar_opcio("Responsable : ", EQUIP).capitalize(),
"prioritat": demanar_opcio("Prioritat : ", PRIORITATS),
"dies": demanar_enter("Dies (1-365) : ", 1, 365),
"etiqueta": demanar_opcio("Etiqueta : ", sorted(ETIQUETES)),
"completada": False,
}
def mostrar_fitxa(tasca):
"""Pinta la fitxa completa de la tasca rebuda."""
estat = "Completada" if tasca["completada"] else "Pendent"
dies_estat = str(tasca["dies"]) + " / " + estat
urgencia = classificar_urgencia(tasca["prioritat"], tasca["dies"])
print("-" * AMPLE)
for etiqueta, clau in (("Titol", "titol"), ("Responsable", "responsable"),
("Prioritat", "prioritat"), ("Etiqueta", "etiqueta")):
print(f"{etiqueta:<14}{tasca[clau]:>{AMPLE - 14}}")
print(f"{'Dies / estat':<14}{dies_estat:>{AMPLE - 14}}")
print(f"{'Urgencia':<14}{urgencia:>{AMPLE - 14}}")
def canviar_prioritat(tasca):
"""Canvia la prioritat de la tasca rebuda (la modifica al lloc)."""
anterior = tasca["prioritat"]
tasca["prioritat"] = demanar_opcio("Nova prioritat: ", PRIORITATS)
print(f"Prioritat de '{tasca['titol']}': {anterior} -> {tasca['prioritat']}")
def marcar_completada(tasca):
"""Marca la tasca com a completada despres de confirmar."""
if tasca["completada"]:
print("La tasca ja estava completada.")
elif confirmar(f"Marcar '{tasca['titol']}' com a completada?"):
tasca["completada"] = True
print("Tasca completada. Bona feina.")
def main():
"""Executa el bucle principal de l'aplicacio."""
tasca = None # None significa 'encara no hi ha tasca'
while True:
mostrar_menu()
opcio = demanar_opcio("Tria una opcio (1-5): ", OPCIONS)
if opcio == "5":
if confirmar("Segur que vols sortir?"):
break
elif opcio == "1":
if tasca is None or confirmar(f"Ja existeix '{tasca['titol']}'. Substituir?"):
tasca = registrar_tasca()
print("Tasca registrada correctament.")
elif tasca is None:
print("Encara no hi ha cap tasca registrada.")
elif opcio == "2":
mostrar_fitxa(tasca)
elif opcio == "3":
canviar_prioritat(tasca)
elif opcio == "4":
marcar_completada(tasca)
pausar()
if __name__ == "__main__":
main()El que ha canviat respecte a la v0.7, i per què importa:
mostrar_fitxa(tasca)té un paràmetre en comptes de cinc. Les sis variables soltes que viatjaven juntes de funció en funció eren, efectivament, una sola cosa; ara tenen nom i forma.- Afegir un camp ja no obliga a tocar cap signatura. Hi hem incorporat
"etiqueta"sense canviar la capçalera de res. Amb la v0.7 hauria suposat un paràmetre més en quatre funcions. - Les funcions d'acció modifiquen el diccionari i no retornen res.
canviar_prioritat(tasca)funciona perquè el diccionari és mutable i es passa per referència, com les llistes de 05-01. El nom anuncia clarament que modifica. ETIQUETESés un conjunt, perquè són valors únics sense ordre l'ús dels quals és comprovar pertinença i oferir opcions; es passasorted(ETIQUETES)ademanar_opcioperquè l'usuari les vegi sempre igual. Itasca is Nonesubstitueix la banderahi_ha_tasca: una dada menys per mantenir sincronitzada.
Continua sense resoldre's el més important: només hi ha una tasca. Però ara que una tasca és un valor únic, desar-les totes serà tan fàcil com ficar-les en una llista.
Errors Comuns i Consells
KeyError en llegir una clau que no existeix. Comprova-ho amb in o fes servir .get(clau, defecte). I recorda que les claus distingeixen majúscules: "Titol" i "titol" són diferents; tria una convenció (minúscules) i respecta-la. Escriure malament una clau en assignar. tasca["responsble"] = "Luis" no dóna error: crea una clau nova. El símptoma apareix després, quan tasca["responsable"] retorna el valor vell. És l'error més traïdor del tipus.
Creure que {} és un conjunt buit. És un diccionari buit; el conjunt buit és set(). I no esperis ordre en un conjunt: si necessites mostrar-lo ordenat, sorted(conjunt).
Fer servir una llista com a clau. TypeError: unhashable type. Si necessites una clau composta, fes servir una tupla (05-04).
Modificar un diccionari mentre el recorres. Afegir o esborrar claus dins del for llança RuntimeError; recorre una còpia (for c in list(d.keys()):) o construeix un diccionari nou. Consell: fes servir el diccionari per a camps, no com a base de dades improvisada. Si acabes amb claus "tasca1", "tasca2", "tasca3", el que vols és una llista de diccionaris (05-04).
Exercicis
Exercici 1: Predir la sortida
Digues què imprimeix cada línia i quins errors es produeixen.
tasca = {"titol": "Cartell fira", "dies": 3}
print(tasca.get("responsable", "sense assignar"))
tasca["dies"] = tasca["dies"] + 2
tasca.setdefault("dies", 99)
tasca.setdefault("prioritat", "mitjana")
print(tasca)
print("Cartell fira" in tasca)
print(len({"a", "b", "a", "b"}))
print({"a", "b"} & {"b", "c"}, {"a", "b"} - {"b", "c"})
print(tasca["completada"])Exercici 2: Resum de l'estudi
Donada la llista de responsables de les tasques obertes, escriu un programa que imprimeixi: quantes tasques porta cada persona (ordenades de més a menys), qui en porta més, i quins membres de l'equip EQUIP = ("Marta", "Luis", "Nuria") no tenen cap tasca assignada. Fes servir un diccionari per comptar i un conjunt per a l'última pregunta.
Exercici 3: Fitxa amb diccionari
Escriu crear_tasca(titol, responsable, prioritat, dies) que retorni el diccionari d'una tasca amb completada en False, i resum(tasca) que retorni una cadena d'una línia amb el títol, el responsable, la prioritat en majúscules, els dies i [X] o [ ] segons l'estat. Afegeix aplicar_canvis(tasca, canvis) que rebi un diccionari de canvis i els apliqui, avisant si alguna clau no existia a la tasca.
Solucions
Solució 1.
sense assignar
{'titol': 'Cartell fira', 'dies': 5, 'prioritat': 'mitjana'}
False
2
{'b'} {'a'}
KeyError: 'completada'.get amb defecte no falla. tasca["dies"] + 2 deixa 5, i setdefault("dies", 99) no el toca perquè la clau ja existeix; setdefault("prioritat", ...) sí que la crea. "Cartell fira" in tasca és False perquè in mira claus, no valors. El conjunt {"a","b","a","b"} té 2 elements. La intersecció és {'b'} i la diferència {'a'}. I l'última línia llança KeyError perquè mai no es va crear aquesta clau: amb tasca.get("completada", False) hauria retornat False.
Solució 2.
EQUIP = ("Marta", "Luis", "Nuria")
assignacions = ["Marta", "Luis", "Marta", "Marta", "Luis"]
recompte = {}
for nom in assignacions:
recompte[nom] = recompte.get(nom, 0) + 1
for nom, total in sorted(recompte.items(), key=lambda p: p[1], reverse=True):
print(f"{nom:<10}{total:>3} tasques")
print("Qui en porta mes:", max(recompte, key=recompte.get))
sense_tasques = set(EQUIP) - set(assignacions)
print("Sense tasques:", ", ".join(sorted(sense_tasques)) or "ningu")Imprimeix «Marta 3 tasques», «Luis 2 tasques», «Qui en porta mes: Marta» i «Sense tasques: Nuria». L'última part és l'exemple perfecte de per a què serveix un conjunt: set(EQUIP) - set(assignacions) respon «qui és a l'equip i no a les assignacions» en una sola expressió, sense bucles ni banderes. Amb llistes hauria calgut recórrer l'equip comprovant cada nom.
Solució 3.
def crear_tasca(titol, responsable, prioritat, dies):
"""Retorna el diccionari d'una tasca nova, pendent per defecte."""
return {"titol": titol, "responsable": responsable,
"prioritat": prioritat, "dies": dies, "completada": False}
def resum(tasca):
"""Retorna una linia amb les dades principals de la tasca."""
marca = "[X]" if tasca["completada"] else "[ ]"
return (f"{marca} {tasca['titol']:<24}{tasca['responsable']:>8}"
f"{tasca['prioritat'].upper():>8}{tasca['dies']:>4}d")
def aplicar_canvis(tasca, canvis):
"""Aplica els canvis a la tasca i avisa de les claus desconegudes."""
for clau, valor in canvis.items():
if clau not in tasca:
print(f"Avis: '{clau}' no es un camp de la tasca; s'ignora.")
continue
tasca[clau] = valor
t = crear_tasca("Cartell fira", "Marta", "alta", 3)
aplicar_canvis(t, {"dies": 4, "completada": True, "color": "vermell"})
print(resum(t)) # [X] Cartell fira Marta ALTA 4dEl que és interessant d'aplicar_canvis és la comprovació if clau not in tasca. Sense ella, un error tipogràfic en el nom del camp afegiria una clau nova en silenci —l'error traïdor de la secció de consells— i mai no sabries per què el canvi «no ha funcionat». Fixa't també que la funció modifica el diccionari rebut i no retorna res: és legítim perquè el nom ho anuncia.
Conclusió
El diccionari guarda parells clau → valor i substitueix la posició pel nom: es crea amb {} o dict(), es llegeix amb d[clau] —que llança KeyError si falta— o amb .get(clau, defecte) —que no falla—, s'amplia i es modifica amb la mateixa assignació, i es recorre amb .keys(), .values() i sobretot .items(). .update() fusiona, .setdefault() garanteix sense esclafar, les claus han de ser immutables i úniques, i la comprensió de diccionari i el patró de recompte de freqüències amb .get(x, 0) + 1 resolen en tres línies coses que abans costaven vint. El conjunt guarda elements únics sense ordre, no s'indexa, es crea amb {...} o set() —mai amb {}, que és un diccionari—, i ofereix unió |, intersecció &, diferència - i diferència simètrica ^, a més de ser l'estructura correcta per desduplicar i per comprovar pertinença.
TascaFàcil està a la v0.9 i una tasca és per fi una sola cosa: un diccionari amb titol, responsable, prioritat, dies, etiqueta i completada. mostrar_fitxa(tasca) té un paràmetre en lloc de cinc, afegir un camp ja no obliga a tocar cap signatura, i les etiquetes de l'estudi viuen en un conjunt. Queda un últim assemblatge: la v0.8 sabia portar moltes tasques però amb llistes paral·leles fràgils, i la v0.9 sap representar una tasca perfectament però només en porta una. Ajuntar totes dues idees —una llista de diccionaris— és el que fa Tuples i estructures imbricades, on a més coneixeràs la tupla, entendràs per fi què retornava return a, b des de 04-02 i aprendràs a llegir expressions com agenda[0]["responsable"] sense parpellejar.
Fonaments de la Programació
Mòdul 1: Introducció a la Programació
- Què és la programació?
- Història de la programació
- Llenguatges de programació
- Entorns de desenvolupament
- Del problema a l'algorisme
Mòdul 2: Conceptes Bàsics
- Variables i tipus de dades
- Operadors i expressions
- Entrada i sortida de dades
- Conversió de tipus i validació de dades
Mòdul 3: Estructures de Control
Mòdul 4: Funcions i Procediments
- Definició i ús de funcions
- Paràmetres i retorn de valors
- Àmbit de variables
- Descompondre un programa en funcions
- Funcions com a valors: lambda i ordre superior
Mòdul 5: Estructures de Dades
- Llistes i arrays
- Cadenes de caràcters
- Diccionaris i conjunts
- Tuples i estructures imbricades
- Desar dades en fitxers: text, CSV i JSON
Mòdul 6: Algorismes Bàsics
Mòdul 7: Objectes i Organització del Codi
- De les dades als objectes: classes i instàncies
- Atributs, mètodes i constructor
- Col·leccions d'objectes
- Mòduls, paquets i importacions
Mòdul 8: Bones Pràctiques i Eines
- Documentació i comentaris
- Depuració i gestió d'errors
- Control de versions
- Proves automatitzades
- Estil, llegibilitat i refactorització
