La lliçó anterior acabava amb una promesa —aquell if que fèiem servir «de puntetes» s'explica a fons aquí— i amb un diagnòstic: TascaFàcil detecta les dades incorrectes, però només sap avisar-ne i posar-hi un valor per defecte. Avisar no és decidir.

Un programa que executa les seves instruccions en ordre, de la primera a l'última, sempre fa el mateix. Els programes útils trien: si la dada és vàlida la fan servir, si no la corregeixen; si la tasca és de prioritat alta la marquen com a urgent, si no la deixen a la cua normal. Aquesta capacitat de triar és la primera de les dues estructures de control d'aquest mòdul; l'altra, repetir, arriba a Bucles. Aquí aprendràs la sintaxi completa d'if, elif i else, per què la indentació en Python és gramàtica i no estètica, com combinar condicions i quan imbricar decisions o aplanar-les.

Contingut

  1. Què és una decisió en un programa
  2. L'if: condició, dos punts i indentació
  3. if / else: el camí alternatiu
  4. if / elif / else: alternatives excloents
  5. Per què elif no és el mateix que diversos if
  6. Condicions compostes amb and, or i not
  7. Condicionals imbricats i com aplanar-los
  8. L'operador ternari i la comparació encadenada
  9. TascaFàcil v0.5.1: decidir en comptes d'avisar
  10. Errors comuns i consells
  11. Exercicis
  12. Conclusió

  1. Què és una decisió en un programa

Una decisió és un punt on el flux es bifurca: s'avalua una condició i, segons sigui vertadera o falsa, s'executa un bloc d'instruccions o un altre. La condició és sempre una expressió booleana de les que vas construir a Operadors i expressions: dies > 5, prioritat == "alta", responsable in EQUIP.

flowchart TD
    A["Instruccio anterior"] --> B{"prioritat == alta ?"}
    B -->|True| C["Marcar com a urgent"]
    B -->|False| D["Deixar a la cua normal"]
    C --> E["Instruccio seguent"]
    D --> E

Tres detalls del diagrama descriuen el que fa el codi: el rombe té només dues sortides, cada branca fa una cosa diferent, i les dues branques es tornen a ajuntar, perquè després de la decisió el programa continua per un únic camí. A Del problema a l'algorisme vas dibuixar diagrames així en pseudocodi; ara els escriurem en Python.

  1. L'if: condició, dos punts i indentació

La forma més simple executa un bloc només si es compleix una condició, i no fa res en cas contrari.

dies_estimats = 12

if dies_estimats > 10:
    print("Tasca llarga: conve partir-la en subtasques.")
print("Fi de l'analisi.")

Amb dies_estimats = 3 la primera línia no s'imprimeix i només veuríem Fi de l'analisi.. La capçalera té tres peces obligatòries —la paraula if, la condició i els dos punts finals, i oblidar-ne qualsevol dona SyntaxError— més una quarta que no és a la línia: el bloc indentat que va a sota.

La indentació és sintaxi

A la majoria de llenguatges el bloc es delimita amb claus { } i la indentació és estètica. En Python la indentació delimita el bloc. No hi ha claus.

prioritat = "baixa"

if prioritat == "alta":
    print("Linia A: dins de l'if")
    print("Linia B: dins de l'if")
print("Linia C: fora de l'if")

Aquí només s'imprimeix la línia C: A i B són dins del bloc perquè estan indentades; C torna al marge esquerre i s'executa sempre, valgui el que valgui prioritat. La convenció oficial (la guia PEP 8, que veuràs a Estil i refactorització) és 4 espais per nivell. Ni 2, ni 8, ni tabuladors; VS Code converteix el tabulador en 4 espais automàticament. Si t'equivoques, Python no ho endevina: deixar buit el bloc d'un if avorta amb IndentationError: expected an indented block after 'if' statement on line 1. Les seves variants són unexpected indent (una línia més indentada del que toca), unindent does not match any outer indentation level (has tancat el bloc a una indentació que no existeix) i TabError (has barrejat tabuladors i espais). Tots quatre s'arreglen mirant la indentació, mai la lògica.

La rigidesa té recompensa: en Python, codi ben indentat i codi correcte són la mateixa cosa. No pot passar que la indentació digui una cosa i les claus una altra, que és un clàssic en altres llenguatges.

  1. if / else: el camí alternatiu

else defineix què passa quan la condició és falsa. No porta condició pròpia —significa «en qualsevol altre cas»— i la seva capçalera és simplement else:.

if hores_dedicades <= hores_estimades:
    print("Dins del pressupost d'hores.")
else:
    print("Pressupost d'hores superat.")

Les dues branques són excloents i exhaustives: sempre se n'executa una, mai totes dues, i no queda cap cas sense cobrir. Amb un if ja arreglem un defecte de la versió 0.5, on els avisos buits imprimien línies en blanc: n'hi ha prou d'envoltar el print en un if avis_prioritat != "":. I com que la cadena buida és falsa (regles de veracitat de Conversió de tipus i validació), el que és idiomàtic és deixar que el mateix valor faci de condició, if avis_prioritat:. Totes dues formes valen; la primera és més explícita per a qui comença.

  1. if / elif / else: alternatives excloents

Quan hi ha més de dos camins, elif (contracció d'else if) encadena condicions. S'avaluen de dalt a baix i s'executa només la primera vertadera; la resta ni es comprova.

prioritat = "mitjana"

if prioritat == "alta":
    termini = 1
elif prioritat == "mitjana":
    termini = 3
elif prioritat == "baixa":
    termini = 10
else:
    termini = 3
    print("Prioritat desconeguda. S'aplica el termini estandard.")

print(f"Dies de termini: {termini}")     # Dies de termini: 3

Al diagrama de flux, cada rombe penja de la sortida False de l'anterior: una condició només s'avalua si totes les prèvies han fallat, i totes les branques desemboquen al mateix punt. Hi pot haver qualsevol nombre d'elif, inclòs cap; l'else final és opcional, però convé posar-lo gairebé sempre com a xarxa de seguretat per al cas imprevist. I l'ordre importa. Si escrivissis if dies > 5: seguit d'elif dies > 15:, la segona branca seria codi mort: cap valor no hi arribaria mai, perquè tot el que és més gran que 15 també és més gran que 5 i la primera branca se'l queda. La regla és col·locar primer les condicions més restrictives.

  1. Per què elif no és el mateix que diversos if

Aquest és el punt que més confusió genera. Mateixa dada, dues versions que només es diferencien en tres lletres:

dies = 20
# --- Versio amb elif ---              # --- Versio amb if solts ---
if dies > 15:                          # if dies > 15:
    categoria = "molt llarga"          #     categoria = "molt llarga"
elif dies > 5:                         # if dies > 5:
    categoria = "llarga"               #     categoria = "llarga"
else:                                  # else:
    categoria = "curta"                #     categoria = "curta"
print(categoria)   # molt llarga       # print(categoria)   # llarga (!)

Amb elif, la primera condició vertadera guanya i les altres se salten. Amb if independents cadascun s'avalua per separat: el primer assigna "molt llarga" i el segon, també cert, el trepitja amb "llarga". A més, aquell else final ja no pertany al primer if, sinó al segon.

Aspecte if / elif / else Diversos if seguits
Branques que s'executen Com a màxim una Totes les que siguin certes
Condicions posteriors No s'avaluen si una ha encertat S'avaluen sempre
Ús típic Classificar un valor en categories (excloents) Comprovar dades diferents (independents)

Pregunta't sempre: són alternatives de la mateixa dada, o comprovacions independents? Classificar una prioritat en alta/mitjana/baixa són alternatives: elif. Validar el títol, el responsable i els dies són comprovacions independents: if separats, com a TascaFàcil.

  1. Condicions compostes amb and, or i not

Una condició pot combinar diverses comprovacions amb els operadors lògics de 02-02. and exigeix que totes les parts siguin vertaderes; or es conforma amb una; not inverteix. Així, if prioritat == "alta" and not completada: selecciona les urgències pendents, i if prioritat == "baixa" or dies > 15: les candidates a ajornar-se.

S'avaluen amb curtcircuit: en A and B, si A és fals, B ni es mira. Això no és un detall acadèmic, és una eina de protecció:

if dies_text.strip().isdigit() and int(dies_text) > 0:
    print("Dies valids")

Si el text no conté dígits, la primera part és False i Python no executa int(dies_text), que hauria llançat un ValueError. Inverteix l'ordre de les dues parts i el programa es trenca. La regla: comprova primer allò que fa segura la comprovació següent. I recorda l'error clàssic de 02-02, que dins d'un if es paga car: if prioritat == "alta" or "mitjana": és sempre vertader, perquè "mitjana" és un text no buit i per tant vertader per si mateix. La forma correcta és if prioritat in ("alta", "mitjana"):.

  1. Condicionals imbricats i com aplanar-los

Un if pot contenir-ne un altre dins del seu bloc; cada nivell afegeix 4 espais d'indentació.

if not completada:
    if prioritat == "alta":
        print(f"Urgencia pendent de {responsable}.")
    else:
        print("Tasca pendent, sense urgencia.")
else:
    print("Tasca completada.")

Funciona, però per saber en quin cas ets cal portar diverses condicions al cap alhora, i la regla de l'ofici és que més de dos o tres nivells d'imbricació són un senyal d'alarma. Molts s'aplanen invertint les preguntes i encadenant elif:

if completada:
    print("Tasca completada.")
elif prioritat != "alta":
    print("Tasca pendent, sense urgencia.")
else:
    print(f"Urgencia pendent de {responsable}.")

La versió imbricada es llegeix com un arbre i és preferible quan la pregunta interior només té sentit si l'exterior és certa; la plana es llegeix com una llista de casos i és preferible quan les condicions descriuen alternatives. Tria la que un company entendria més de pressa.

  1. L'operador ternari i la comparació encadenada

Quan la decisió consisteix només a triar un valor entre dos, hi ha una forma abreujada d'una línia, l'expressió condicional o ternari, amb la forma valor_si if condicio else valor_no:

completada = False
estat = "Completada" if completada else "Pendent"    # Pendent

Equival a un if / else de quatre línies i es llegeix de manera gairebé natural: «estat és "Completada" si completada, si no "Pendent"». El seu avantatge és que, en ser una expressió i no una sentència, cap dins d'una f-string: print(f"Tasca {'llarga' if dies > 10 else 'curta'}") imprimeix Tasca llarga quan dies val 12. Fes-lo servir per triar entre dos valors simples; si cada branca ha d'executar diverses instruccions, o hi ha més de dues alternatives, torna a l'if / elif / else. I no imbriquis mai un ternari dins d'un altre: es torna il·legible.

Comparació encadenada. Per comprovar un interval, Python permet encadenar comparacions com en matemàtiques: if 1 <= dies <= 365:. Equival a dies >= 1 and dies <= 365, però es llegeix millor i avalua dies una sola vegada. L'if dies < 1 or dies > 365 de la versió 0.5 s'escriu ara if not (1 <= dies <= 365). Només és llegible amb comparacions del mateix sentit sobre la mateixa dada, i no el confonguis amb in: l'encadenament comprova un interval continu, in comprova pertinença a un catàleg.

  1. TascaFàcil v0.5.1: decidir en comptes d'avisar

La versió 0.5 detectava els problemes i responia sempre igual: valor per defecte. Ara decidim de veritat, amb tres millores. Davant d'una prioritat invàlida, si és un sinònim reconeixible (urgent, critica) s'interpreta com a alta, i només si és irreconeixible s'aplica el valor per defecte. Davant d'uns dies fora d'interval, es distingeix massa petit (es puja al mínim) de massa gran (es baixa al màxim), en comptes de substituir-los per un número sense relació amb el que s'ha introduït. I davant d'un responsable aliè a l'equip, la tasca passa a la Marta, la coordinadora, i es marca per reassignar.

A més classifiquem la tasca en urgent, normal o ajornable, i els avisos buits deixen d'imprimir línies en blanc.

# tascafacil.py - Estudi Alba
# Versio 0.5.1: el programa decideix, no nomes avisa

AMPLE = 46
HORES_PER_JORNADA = 8
PRIORITATS = ("alta", "mitjana", "baixa")
SINONIMS_ALTA = ("urgent", "urgentissima", "critica", "critic")
EQUIP = ("Marta", "Luis", "Nuria")
COORDINADORA = "Marta"
DIES_MIN = 1
DIES_MAX = 365
DIES_PER_DEFECTE = 5

# --- 1. Titol: presencia ---
titol = input("Titol de la tasca             : ").strip()
titol = titol if titol != "" else "(sense titol)"

# --- 2. Responsable: domini, amb reassignacio raonada ---
responsable = input("Responsable (Marta/Luis/Nuria): ").strip().capitalize()
avis_responsable = ""
requereix_reassignacio = False
if responsable not in EQUIP:
    avis_responsable = f"'{responsable}' no es de l'equip. Passa a {COORDINADORA}."
    responsable = COORDINADORA
    requereix_reassignacio = True

# --- 3. Prioritat: domini, interpretant sinonims ---
prioritat = input("Prioritat (alta/mitjana/baixa): ").strip().lower()
avis_prioritat = ""
if prioritat in PRIORITATS:
    pass
elif prioritat in SINONIMS_ALTA:
    avis_prioritat = f"'{prioritat}' s'interpreta com a prioritat alta."
    prioritat = "alta"
else:
    avis_prioritat = f"'{prioritat}' no es una prioritat. S'assigna 'mitjana'."
    prioritat = "mitjana"

# --- 4. Dies estimats: tipus i coherencia, ajustant a l'interval ---
dies_text = input("Dies estimats                 : ").strip()
avis_dies = ""
if not dies_text.isdigit():
    avis_dies = f"'{dies_text}' no es un numero. S'assignen {DIES_PER_DEFECTE} dies."
    dies_estimats = DIES_PER_DEFECTE
else:
    dies_estimats = int(dies_text)
    if dies_estimats < DIES_MIN:
        avis_dies = f"{dies_estimats} dies es massa poc. S'ajusta a {DIES_MIN}."
        dies_estimats = DIES_MIN
    elif dies_estimats > DIES_MAX:
        avis_dies = f"{dies_estimats} dies excedeix el maxim. S'ajusta a {DIES_MAX}."
        dies_estimats = DIES_MAX

# --- 5. Proces: classificacio i sortida ---
hores_estimades = dies_estimats * HORES_PER_JORNADA
completada = False
if prioritat == "alta" and not completada:
    classificacio = "URGENT"
elif prioritat == "mitjana" or dies_estimats <= 3:
    classificacio = "NORMAL"
else:
    classificacio = "AJORNABLE"
estat = "Completada" if completada else "Pendent"
print("=" * AMPLE)
print(f"{'Titol':<16}{titol:>{AMPLE - 16}}")
print(f"{'Responsable':<16}{responsable:>{AMPLE - 16}}")
print(f"{'Prioritat':<16}{prioritat:>{AMPLE - 16}}")
print(f"{'Dies / hores':<16}{f'{dies_estimats} / {hores_estimades}':>{AMPLE - 16}}")
print(f"{'Estat':<16}{f'{estat}, {classificacio}':>{AMPLE - 16}}")
print("=" * AMPLE)
if requereix_reassignacio:
    print(f">> {COORDINADORA} ha de reassignar aquesta tasca.")
if avis_responsable or avis_prioritat or avis_dies:
    print("\nIncidencies detectades:")
    if avis_responsable:
        print(" -", avis_responsable)
    if avis_prioritat:
        print(" -", avis_prioritat)
    if avis_dies:
        print(" -", avis_dies)

Amb les entrades Cartell fira del llibre, Pere, URGENTISSIMA i 800, la sortida és:

==============================================
Titol                  Cartell fira del llibre
Responsable                              Marta
Prioritat                                 alta
Dies / hores                        365 / 2920
Estat                          Pendent, URGENT
==============================================
>> Marta ha de reassignar aquesta tasca.

Incidencies detectades:
 - 'Pere' no es de l'equip. Passa a Marta.
 - 'urgentissima' s'interpreta com a prioritat alta.
 - 800 dies excedeix el maxim. S'ajusta a 365.

A la versió 0.5, urgentissima es convertia en mitjana (perdent la intenció de l'usuari) i 800 en 5 (un número inventat). Ara cada correcció conserva la informació de la dada original. Això és decidir.

El pass de la primera branca és una instrucció que no fa res, i existeix perquè Python exigeix que tot bloc tingui almenys una instrucció: és la manera de dir «aquí no cal fer res, i és intencionat». I la classificació fa servir elif prioritat == "mitjana" or dies_estimats <= 3 perquè una tasca de prioritat baixa però de tres dies o menys convé despatxar-la, no ajornar-la: les regles de negoci reals tenen aquesta forma. Tot i així, el cap solt queda més visible que mai: quan la dada és irreconeixible, el que caldria seria tornar a preguntar, no inventar un valor. Per a això cal repetir.

Errors Comuns i Consells

Oblidar els dos punts. if dies > 5 sense : dona SyntaxError: expected ':'. Passa igual amb if, elif i else. I else prioritat == "baixa": tampoc no existeix: l'else mai no porta condició; si la necessites, és un elif.

Confondre = amb ==. if prioritat = "alta": és un SyntaxError. L'un assigna, l'altre compara; Python et protegeix aquí, però altres llenguatges no.

Encadenar if quan volies elif. L'error de l'apartat 5, i el pitjor de tots perquè no dona error: simplement el resultat és un altre.

Deixar codi mort per l'ordre de les condicions. if dies > 5 abans d'elif dies > 15 fa inabastable la segona branca. Ordena del més restrictiu al més general. I escriure if prioritat == "alta" or "mitjana" és sempre vertader: fes servir in ("alta", "mitjana").

Consell: posa sempre un else final a les cadenes d'elif. El dia que aparegui un valor imprevist, l'else t'ho dirà en comptes de deixar una variable sense definir.

Consell: extreu les condicions llargues a una variable amb nom. es_urgent = prioritat == "alta" and not completada, i després if es_urgent:. El codi es llegeix com una frase i la condició es pot imprimir per depurar-la.

Exercicis

Exercici 1: Predir el resultat

Sense executar res, indica què imprimeix cada fragment.

# a)
dies = 20
if dies > 15:
    print("molt llarga")
elif dies > 5:
    print("llarga")
else:
    print("curta")

# b)
dies = 20
if dies > 15:
    print("molt llarga")
if dies > 5:
    print("llarga")
else:
    print("curta")

Exercici 2: Classificador de càrrega de treball

Escriu carrega_treball.py que demani el nom d'una persona de l'equip i les hores assignades aquesta setmana, i que:

  1. Normalitzi i validi el nom contra EQUIP; si no hi pertany, avisi i l'assigni a "Marta". Validi amb .isdigit() que les hores són un enter entre 0 i 60; si no, avisi i assigni 40.
  2. Classifiqui la càrrega amb if / elif / else: "Infrautilitzat" per sota de 20, "Correcte" de 20 a 40, "Sobrecarregat" de 41 a 50 i "Risc de burnout" per damunt.
  3. Calculi amb un ternari el text "jornada completa" o "jornada parcial" segons si arriba a 35 hores.
  4. Si està sobrecarregada i a més és la Marta, imprimeixi un avís extra: la coordinadora no pot ser el coll d'ampolla. Mostri per últim una fitxa alineada, i les incidències només si n'hi ha.

Exercici 3: Aplanar una imbricació

Reescriu sense cap if imbricat, amb el mateix comportament, aquesta estructura: un if titol != "": conté un if responsable in EQUIP:, que al seu torn conté un if dies >= 1: amb el missatge "Tasca valida"; els tres else imprimeixen, de dins cap enfora, "Dies incorrectes", "Responsable incorrecte" i "Falta el titol".

Solucions

Solució 1.

Sortida Per què
a molt llarga Les dues primeres condicions són certes, però elif talla després de la primera
b molt llarga i llarga Són dos if independents i totes dues condicions són certes; l'else pertany al segon

És el mateix codi tret de tres lletres, i dona sortides diferents: dues línies on el programador n'esperava una, sense cap error que ho delati.

Solució 2.

# carrega_treball.py - Estudi Alba
AMPLE = 42
EQUIP = ("Marta", "Luis", "Nuria")
COORDINADORA = "Marta"
HORES_PER_DEFECTE = 40
nom = input("Persona (Marta/Luis/Nuria): ").strip().capitalize()
avis_nom = ""
if nom not in EQUIP:
    avis_nom = f"'{nom}' no es de l'equip. S'assigna a {COORDINADORA}."
    nom = COORDINADORA

hores_text = input("Hores assignades (0-60)   : ").strip()
avis_hores = ""
if hores_text.isdigit() and 0 <= int(hores_text) <= 60:
    hores = int(hores_text)
else:
    avis_hores = f"'{hores_text}' no es valid. S'assignen {HORES_PER_DEFECTE} h."
    hores = HORES_PER_DEFECTE

if hores < 20:
    classificacio = "Infrautilitzat"
elif hores <= 40:
    classificacio = "Correcte"
elif hores <= 50:
    classificacio = "Sobrecarregat"
else:
    classificacio = "Risc de burnout"

jornada = "jornada completa" if hores >= 35 else "jornada parcial"

print(f"{nom:<18}{f'{hores} h, {jornada}':>{AMPLE - 18}}")
print(f"{'Classificacio':<18}{classificacio:>{AMPLE - 18}}")

if hores > 40 and nom == COORDINADORA:
    print(">> La coordinadora esta sobrecarregada: repartir feina.")
if avis_nom or avis_hores:
    print(avis_nom, avis_hores)

Dos detalls. La validació de les hores aprofita el curtcircuit: int(hores_text) només s'executa si .isdigit() ja ha dit que és convertible, així que una sola condició cobreix el tipus i l'interval. I a la cadena d'elif, com que cada branca només s'avalua si l'anterior ha fallat, en arribar a elif hores <= 40 ja sabem que hores >= 20: les condicions d'un elif arrosseguen implícitament la negació de les anteriors, i aprofitar-ho simplifica molt el codi.

Solució 3.

if titol == "":
    print("Falta el titol")
elif responsable not in EQUIP:
    print("Responsable incorrecte")
elif dies < 1:
    print("Dies incorrectes")
else:
    print("Tasca valida")

Aquesta forma s'anomena clàusules de guarda: primer els casos d'error, cadascun amb el seu missatge, i el cas correcte al final sense indentació acumulada. Afegir una validació nova és afegir un elif, no obrir un altre nivell. I l'ordre de lectura coincideix amb l'ordre de les comprovacions, cosa que a la versió imbricada es perdia: en llegir "Dies incorrectes" allà dins no era evident que el títol i el responsable ja fossin correctes.

Conclusió

El teu programa ja sap triar. Saps escriure un if amb la seva condició, els seus dos punts i el seu bloc indentat de 4 espais, i entens que en Python la indentació és gramàtica: IndentationError és el preu d'escriure-la malament. Saps afegir un else, encadenar elif per a alternatives excloents i —el més important— distingir quan un problema demana elif i quan demana diversos if independents, perquè aquesta confusió no produeix error sinó resultats incorrectes. Saps combinar condicions amb and, or i not aprofitant el curtcircuit per protegir-te d'un ValueError, imbricar quan la pregunta interior depèn de l'exterior i aplanar amb clàusules de guarda quan no, triar un valor en una línia amb el ternari i comprovar intervals amb 1 <= dies <= 365.

TascaFàcil ha passat a la versió 0.5.1 i ha canviat d'actitud: ja no substitueix en silenci les dades estranyes, sinó que interpreta el que pot, ajusta el que se surt d'interval, reassigna amb criteri a la coordinadora i classifica la feina en urgent, normal o ajornable. Els avisos buits han desaparegut, tal com vam prometre en tancar el mòdul 2. Però queda una decisió que el programa continua sense poder prendre, i és la més natural: quan la Marta escriu una prioritat que no existeix, el lògic no és corregir-la ni inventar-la, sinó demanar-la un altre cop. Amb un if és impossible: s'executa una vegada i segueix endavant. Tampoc no podem registrar una segona tasca sense rellançar el programa, ni sumar els dies de les cinc tasques que la Marta té al cap. Tot això és el mateix: repetir. És el que aprendràs a Bucles, on while i for tancaran per fi el cap solt de tornar a preguntar fins que la dada sigui vàlida.

© Copyright 2026. Tots els drets reservats