Al final del mòdul anterior vam deixar el projecte Papyrus amb l'entorn a punt i uns quants scripts funcionant, i vam prometre que els teus programes començarien a prendre decisions. Aquesta lliçó compleix la promesa: aprendràs a usar if, elif i else perquè Python executi un codi o un altre segons les condicions que es compleixin. És la diferència entre un script que sempre fa el mateix i un programa que reacciona: "hi ha estoc de L'Odissea?", "en Lluís és soci? Doncs aplica-li el descompte". Sense condicionals no hi ha lògica de negoci possible, així que aquesta és probablement la lliçó més important del curs fins ara.
Contingut
- La sentència
if: prendre la primera decisió else: el camí alternatiuelif: encadenar diverses condicions- Condicionals imbricats
- Condicions compostes amb
and,orinot - Truthiness: valors que es comporten com
TrueoFalse - L'operador ternari: condicionals en una línia
La sentència if: prendre la primera decisió
L'estructura bàsica d'un condicional en Python és la sentència if (en anglès, "si"). La seva sintaxi és:
Fixa't en tres detalls fonamentals:
- La condició és qualsevol expressió que Python pugui avaluar com a
TrueoFalse(els booleans que vas veure al mòdul 1). - Els dos punts (
:) al final de la línia de l'ifsón obligatoris. Oblidar-los és l'error de sintaxi més freqüent quan es comença. - El bloc indentat (amb 4 espais, com ja saps per PEP 8) defineix quines instruccions depenen de l'
if. En Python la indentació no és estètica: és l'estructura del programa.
Resolguem la primera pregunta que l'Anna es fa cada vegada que algú demana un llibre a Papyrus: hi ha estoc?
titol = "L'Odissea"
estoc = 4
if estoc > 0:
print(f"'{titol}' esta disponible ({estoc} unitats).")
print("Consulta finalitzada.")Sortida:
Què ha passat exactament?
- Python avalua
estoc > 0. Com queestocval4, l'expressió donaTrue. - En ser certa, s'executa el bloc indentat (el
printdel missatge de disponibilitat). - L'última línia,
print("Consulta finalitzada."), no està indentada, així que no forma part de l'if: s'executa sempre, hi hagi estoc o no.
Si canvies estoc = 0 i tornes a executar, veuràs només Consulta finalitzada.: el bloc de l'if se salta del tot.
El flux d'un if, vist com a diagrama
flowchart TD
A[Inici] --> B{estoc > 0}
B -- True --> C[Mostrar disponibilitat]
B -- False --> D[Continuar]
C --> D
D --> E[Consulta finalitzada]
El programa arriba a una bifurcació, tria un camí segons la condició i després tots dos camins es tornen a ajuntar.
else: el camí alternatiu
Sovint no n'hi ha prou amb "fes això si es compleix": també vols fer una altra cosa si no es compleix. Per a això existeix else ("si no"):
titol = "Hamlet"
estoc = 0
if estoc > 0:
print(f"'{titol}' esta disponible ({estoc} unitats).")
else:
print(f"'{titol}' esta esgotat. Anna ha de reposar-lo.")Sortida:
Regles de l'else:
- No porta condició pròpia: s'executa quan la condició de l'
ifés falsa. - Va al mateix nivell d'indentació que el seu
if, també amb dos punts. - És opcional: un
ifpot anar perfectament sol, com al primer exemple.
Amb if/else garanteixes que exactament un dels dos blocs s'executa sempre.
elif: encadenar diverses condicions
I si hi ha més de dos escenaris? L'Anna vol classificar l'estoc de cada llibre en tres nivells: esgotat, en queden poques unitats, o estoc suficient. Per encadenar condicions s'usa elif (contracció d'else if):
titol = "El Quixot"
estoc = 8
if estoc == 0:
print(f"'{titol}': ESGOTAT. Demanar al distribuidor.")
elif estoc <= 3:
print(f"'{titol}': queden poques unitats ({estoc}).")
else:
print(f"'{titol}': estoc suficient ({estoc} unitats).")Sortida:
Com ho avalua Python, en ordre i de dalt a baix:
estoc == 0→8 == 0ésFalse. Se salta aquest bloc.estoc <= 3→8 <= 3ésFalse. Se salta també.- Cap condició no s'ha complert, així que s'executa l'
else.
Punts clau de les cadenes if/elif/else:
- Pots posar tants
elifcom necessitis. - Tan bon punt una condició dona
True, s'executa el seu bloc i la resta de la cadena s'ignora, encara que altres condicions també fossin certes. L'ordre importa. - L'
elsefinal és opcional, però sol ser bona idea incloure'l com a "cas per defecte".
Aquest segon punt mereix un exemple. Observa què passa si ordenem malament les condicions:
estoc = 0
# MAL ordenat: la condicio amplia va primer
if estoc <= 3:
print("Queden poques unitats.") # S'executa aixo!
elif estoc == 0:
print("ESGOTAT.") # Mai s'arriba aqui amb estoc 0Amb estoc = 0, la primera condició (0 <= 3) ja és certa, així que el missatge d'"ESGOTAT" no es mostrarà mai. Regla pràctica: col·loca primer les condicions més específiques i deixa les més generals per al final.
Condicionals imbricats
Un bloc if pot contenir, al seu torn, un altre if. És el que anomenem imbricació, i serveix per a decisions que depenen d'una decisió anterior. A Papyrus: primer comprovem si hi ha estoc i, només si n'hi ha, comprovem si el client és soci per aplicar-li el descompte.
titol = "L'Odissea"
preu = 12.50
estoc = 4
es_soci = True # en Lluis es soci de Papyrus
DESCOMPTE_SOCI = 0.05
if estoc > 0:
print(f"Venent '{titol}'...")
if es_soci:
preu_final = preu * (1 - DESCOMPTE_SOCI)
print(f"Descompte de soci aplicat: {preu_final:.2f} €")
else:
preu_final = preu
print(f"Preu sense descompte: {preu_final:.2f} €")
else:
print(f"No es pot vendre '{titol}': sense estoc.")Sortida:
Observa la indentació: l'if es_soci: està indentat 4 espais (dins del primer if), i els seus blocs interns són a 8 espais. Cada nivell d'imbricació afegeix 4 espais.
Consell d'estil: dos nivells d'imbricació es llegeixen bé; tres comencen a costar; quatre o més solen indicar que el codi necessita reorganitzar-se (sovint amb condicions compostes, que veiem tot seguit, o amb funcions, que veuràs al mòdul 3).
Condicions compostes amb and, or i not
Ja coneixes els operadors lògics del mòdul 1. El seu gran moment és precisament aquest: combinar diverses comprovacions en una sola condició.
| Operador | Resultat | Exemple | Avalua a |
|---|---|---|---|
and |
True només si totes dues parts són True |
estoc > 0 and es_soci |
True si hi ha estoc i és soci |
or |
True si almenys una part és True |
estoc == 0 or preu > 50 |
True si està esgotat o és car |
not |
Inverteix el valor | not es_soci |
True si no és soci |
Amb and podem reescriure l'exemple anterior sense imbricar, quan només ens interessa un cas concret:
titol = "L'Odissea"
preu = 12.50
estoc = 4
es_soci = True
DESCOMPTE_SOCI = 0.05
if estoc > 0 and es_soci:
preu_final = preu * (1 - DESCOMPTE_SOCI)
print(f"Venda a soci: '{titol}' per {preu_final:.2f} €")
elif estoc > 0:
print(f"Venda normal: '{titol}' per {preu:.2f} €")
else:
print(f"'{titol}' esta esgotat.")I amb or, l'Anna pot detectar llibres que requereixen la seva atenció per qualsevol de dos motius:
Dos detalls importants dels operadors lògics en condicions:
- Avaluació en curtcircuit: en
a and b, siaésFalse, Python ni tan sols avaluab(el resultat ja no pot serTrue). Ena or b, siaésTrue, no avaluab. Això s'aprofita per escriure condicions segures, comif estoc > 0 and 10 / estoc < 3:— la divisió no s'executa mai siestocés0. - Encadenament de comparacions: Python permet escriure
if 1 <= estoc <= 3:en lloc deif estoc >= 1 and estoc <= 3:. Totes dues són equivalents, però la primera és més llegible i molt idiomàtica.
Quan una condició composta barreja and i or, usa parèntesis per deixar clara la intenció (recorda que and té prioritat sobre or):
Truthiness: valors que es comporten com True o False
Fins ara les nostres condicions eren comparacions explícites (estoc > 0). Però Python permet posar qualsevol valor com a condició, i el convertirà automàticament a booleà. Aquesta conversió implícita s'anomena truthiness (una cosa així com "veracitat").
La regla és senzilla de recordar: el que és buit i el que és nul és fals; la resta, cert. Aquests són els valors falsy (que avaluen a False) més habituals:
| Valor | Tipus | Per què és falsy? |
|---|---|---|
False |
bool | És el fals literal |
0, 0.0 |
int, float | El zero numèric |
"" |
str | Cadena buida |
None |
NoneType | Absència de valor |
[], (), {} |
col·leccions | Col·leccions buides (les veuràs al mòdul 4) |
Tota la resta és truthy: 1, -3, 0.01, "hola", " " (una cadena amb un espai no està buida!), etc.
Ho pots comprovar al REPL amb bool():
Per a què serveix a la pràctica? Per escriure condicions més naturals. Aquestes dues versions són equivalents, i la segona és la idiomàtica en Python:
estoc = 4
# Versio explicita
if estoc > 0:
print("Hi ha estoc.")
# Versio idiomatica usant truthiness
if estoc:
print("Hi ha estoc.")I molt útil amb input(), que com recordaràs sempre retorna str. Si l'usuari prem Intro sense escriure res, retorna la cadena buida "", que és falsy:
nom = input("Nom del client (Intro per ometre): ")
if not nom:
nom = "Client anonim"
print(f"Benvingut a Papyrus, {nom}.")Aquí not nom és True quan nom està buit, així que assignem un valor per defecte. Aquest patró (comprovar si una entrada està buida) és constant en programes reals.
Matís: usa truthiness quan la pregunta natural sigui "hi ha alguna cosa aquí?" (hi ha text?, hi ha unitats?). Si la pregunta és sobre un valor concret ("l'estoc és exactament 0?", "la resposta és 's'?"), la comparació explícita (==) comunica millor la intenció.
L'operador ternari: condicionals en una línia
Quan l'única cosa que fa un if/else és triar entre dos valors, Python ofereix una forma compacta anomenada expressió condicional o operador ternari:
Compara la versió clàssica amb la ternària per calcular el preu d'en Lluís:
preu = 9.95 # Hamlet
es_soci = True
DESCOMPTE_SOCI = 0.05
# Versio classica: 4 linies
if es_soci:
preu_final = preu * (1 - DESCOMPTE_SOCI)
else:
preu_final = preu
# Versio ternaria: 1 linia, mateix resultat
preu_final = preu * (1 - DESCOMPTE_SOCI) if es_soci else preu
print(f"Preu final: {preu_final:.2f} €")També llueix dins de les f-strings, per exemple per al tiquet de Papyrus:
Regles d'ús del ternari:
- És una expressió: produeix un valor, així que pots assignar-la, imprimir-la o passar-la a una funció. Un
ifnormal és una sentència i no produeix cap valor. - Es llegeix "A si condició, si no B", que és gairebé llenguatge natural.
- Usa'l només per a eleccions simples entre dos valors. Si necessites executar diverses instruccions, o imbricar ternaris dins de ternaris, torna a l'
if/elseclàssic: la llegibilitat mana.
Errors Comuns i Consells
- Oblidar els dos punts al final d'
if,elifoelseprodueixSyntaxError. És l'errada número u de tot principiant; revisa-ho abans que res. - Confondre
=amb==:if estoc = 0:és un error de sintaxi.=assigna,==compara. Python et protegeix aquí negant-se a executar-ho. - Indentació inconsistent: barrejar 4 espais amb tabuladors o amb 3 espais provoca
IndentationError. Configura el teu editor (VS Code ho fa per defecte) perquè insereixi 4 espais en prémer Tab. - Ordenar malament els
elif: com has vist, si una condició àmplia va abans que una d'específica, l'específica no s'executarà mai. Ordena del més concret al més general. - Comparar floats amb
==: per la imprecisió dels decimals que vam veure al mòdul 1,0.1 + 0.2 == 0.3donaFalse. Per a diners en condicionals, compara amb un marge:abs(total - esperat) < 0.001. if es_soci == True:funciona, però és redundant:es_socija és un booleà. Escriuif es_soci:i, per al cas contrari,if not es_soci:.- Consell: quan una condició composta es torni difícil de llegir, guarda-la en una variable amb un nom descriptiu:
pot_comprar = estoc > 0 and es_socii desprésif pot_comprar:. El codi s'autodocumenta.
Exercicis
Exercici 1: classificador d'estoc
Escriu un script nivell_estoc.py que, donades les variables titol i estoc, imprimeixi:
"ESGOTAT — demanar urgent"si l'estoc és 0."Estoc baix — reposar aviat"si està entre 1 i 3 (tots dos inclosos)."Estoc correcte"si està entre 4 i 10."Exces d'estoc — no demanar-ne mes"si és més gran que 10.
Prova'l amb els tres llibres del catàleg: L'Odissea (4), Hamlet (6) i El Quixot (8).
Exercici 2: preu final d'una venda
Amplia venda_soci.py: donades les variables preu, es_soci i estoc, l'script ha de:
- Si no hi ha estoc, imprimir
"Venda impossible: sense estoc"i res més. - Si hi ha estoc, calcular el preu amb
IVA_LLIBRES = 0.04inclòs. - Aplicar a més
DESCOMPTE_SOCI = 0.05sobre el preu base només si el client és soci (el descompte s'aplica abans de l'IVA). - Imprimir el preu final amb dos decimals.
Comprova que per a El Quixot (15.90 €) comprat per en Lluís (soci) el resultat és 15.71 €.
Exercici 3: validador d'alta de llibre
A fitxa_llibre.py vam prometre validar l'entrada. Fes el primer pas: demana amb input() el títol d'un llibre i el seu preu. Usant truthiness i un ternari:
- Si el títol està buit, imprimeix
"Error: el titol es obligatori". - Si no, converteix el preu a
floati imprimeix, en una sola f-string amb ternari,"<titol>: economic"si costa menys de 12 € o"<titol>: premium"altrament.
Solucions
Solució 1:
titol = "L'Odissea"
estoc = 4
if estoc == 0:
missatge = "ESGOTAT — demanar urgent"
elif estoc <= 3:
missatge = "Estoc baix — reposar aviat"
elif estoc <= 10:
missatge = "Estoc correcte"
else:
missatge = "Exces d'estoc — no demanar-ne mes"
print(f"{titol}: {missatge}")Fixa't que no cal escriure 1 <= estoc <= 3 al segon cas: si arribem a aquest elif, ja sabem que estoc no és 0, així que n'hi ha prou amb estoc <= 3. Cada branca pot recolzar-se en el fet que les anteriors han fallat. Els tres llibres del catàleg cauen a "Estoc correcte".
Solució 2:
IVA_LLIBRES = 0.04
DESCOMPTE_SOCI = 0.05
preu = 15.90 # El Quixot
es_soci = True # en Lluis
estoc = 8
if estoc == 0:
print("Venda impossible: sense estoc")
else:
base = preu * (1 - DESCOMPTE_SOCI) if es_soci else preu
preu_final = base * (1 + IVA_LLIBRES)
print(f"Preu final: {preu_final:.2f} €")Càlcul pas a pas: 15.90 × 0.95 = 15.105 (descompte de soci) i 15.105 × 1.04 = 15.7092, que la f-string arrodoneix a 15.71 €. El ternari resol en una línia l'elecció del preu base.
Solució 3:
titol = input("Titol del llibre: ")
if not titol:
print("Error: el titol es obligatori")
else:
preu = float(input("Preu (€): "))
print(f"{titol}: {'economic' if preu < 12 else 'premium'}")not titol és True quan l'usuari prem Intro sense escriure (cadena buida, falsy). El ternari va dins de la f-string, entre claus, perquè és una expressió i produeix un valor. Nota: si l'usuari escriu un preu no numèric, float() fallarà amb ValueError; aprendrem a gestionar-ho amb elegància al mòdul 7.
Conclusió
Els teus programes ja saben decidir. Has après la sentència if amb les seves companyes elif i else, a imbricar decisions quan una depèn d'una altra, a combinar comprovacions amb and/or/not (inclòs el curtcircuit), a aprofitar el truthiness dels valors buits i a condensar eleccions simples amb l'operador ternari. Papyrus ja pot respondre a les seves dues preguntes de negoci essencials: si hi ha estoc i si toca aplicar el descompte de soci.
Però continuem decidint llibre a llibre, amb variables soltes. L'Anna té un catàleg sencer, i comprovar l'estoc de cada títol copiant i enganxant ifs no escala. El que necessitem és repetir una operació sobre molts elements, i d'això tracta exactament la lliçó següent: els bucles for i while, amb els quals recorrerem el catàleg complet de Papyrus i sumarem la caixa del dia en poques línies.
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
