Tancàvem la lliçó anterior amb TascaFàcil calculant dies restants, percentatges d'avanç i urgències, però amb dues mancances molt visibles: la fitxa s'imprimia a raó d'una línia per dada, il·legible, i totes les dades continuaven escrites dins del codi. Per registrar la tasca d'un altre client calia obrir l'editor.

Aquesta lliçó arregla les dues coses, i amb això el teu programa creua una frontera important: deixa de ser una cosa que s'edita per convertir-se en una cosa que es fa servir. Un programa que es fa servir té dos punts de contacte amb el món: l'entrada (les dades que rep) i la sortida (els resultats que mostra). En Python aquests dos punts es diuen input() i print().

Ja coneixes print() des del mòdul 1, però només en la seva forma més simple. Aquí el veuràs a fons: diversos arguments, els paràmetres sep i end, els caràcters d'escapada, i sobretot les f-strings, l'eina amb què es compon text en el Python modern i amb la qual per fi podràs barrejar paraules i variables en una sola línia, alinear columnes i mostrar decimals amb la precisió que vulguis. Després arribarà input(), i amb ell un detall que condiciona tot el que ve: input() retorna sempre text, encara que l'usuari teclegi un número.

Contingut

  1. Entrada i sortida: els dos punts de contacte d'un programa
  2. print() amb diversos arguments
  3. Els paràmetres sep i end
  4. Caràcters d'escapada: \n, \t i les cometes
  5. f-strings: interpolació de variables
  6. Expressions dins d'una f-string
  7. Especificadors de format: decimals i alineació
  8. Altres maneres de formatar que veuràs en codi aliè
  9. input(): demanar dades per teclat
  10. El punt capital: input() sempre retorna text
  11. TascaFàcil: la fitxa es demana i es presenta
  12. Errors comuns i consells
  13. Exercicis
  14. Conclusió

  1. Entrada i sortida: els dos punts de contacte d'un programa

Qualsevol programa, des del més simple fins a un sistema bancari, segueix el mateix esquema de tres fases:

flowchart LR
    A["ENTRADA<br/>dades que arriben"] --> B["PROCES<br/>calculs i decisions"]
    B --> C["SORTIDA<br/>resultats que es mostren"]

Fins ara has treballat al centre: variables (02-01) i expressions (02-02) són procés pur. L'entrada estava fixada al codi i la sortida era rudimentària. Anem a cobrir els dos extrems.

Les dades poden entrar per moltes vies —teclat, fitxers, xarxa, sensors— i sortir per unes altres tantes. En aquest curs comencem per la més directa: el teclat per entrar i la pantalla (concretament, el terminal) per sortir. Llegir i escriure fitxers arribarà a Desar dades en fitxers.

Un advertiment de fons que convé tenir present des del primer dia: tot el que entra des de fora és sospitós. L'usuari pot teclejar un número on esperaves un nom, deixar el camp buit o escriure «ALTA» en majúscules. Comprovar que les dades són correctes s'anomena validar, i és el tema de la propera lliçó. Aquí ens ocupem de rebre-les i mostrar-les.

  1. print() amb diversos arguments

Fins ara has fet servir print() amb un sol valor. Però admet diversos, separats per comes:

titol = "Logotip Forn Sole"
responsable = "Luis"

print("Titol:", titol)
print("Responsable:", responsable)

Sortida:

Titol: Logotip Forn Sole
Responsable: Luis

Això resol de cop el problema que vam deixar pendent a la lliçó anterior: recorda que "Titol: " + titol funcionava només amb textos, i que "Dies: " + 3 donava TypeError. Amb comes no hi ha problema, perquè print() converteix cada valor a text automàticament:

dies_restants = 7
percentatge = 37.5
completada = False
data_lliurament = None

print("Dies restants:", dies_restants)        # Dies restants: 7
print("Percentatge:", percentatge)            # Percentatge: 37.5
print("Completada:", completada)              # Completada: False
print("Lliurament:", data_lliurament)         # Lliurament: None

Números, booleans, None: print() els mostra tots sense protestar.

Hi ha dos detalls a observar. Primer: entre cada argument apareix un espai, posat per Python, no per tu. Per això "Titol:" no porta espai final i tot i així la sortida es veu bé. Segon: no hi ha límit d'arguments.

print("Tasca", 1, "de", 3, "->", 33.3, "%")
Tasca 1 de 3 -> 33.3 %

Fixa't en el resultat: el % apareix separat del número perquè l'espai automàtic es posa entre tots els arguments. Aquest espai automàtic és còmode però també rígid; l'apartat següent explica com controlar-lo.

I un print() sense arguments imprimeix una línia en blanc:

print()      # linia buida

És més net que print(""), que fa el mateix.

  1. Els paràmetres sep i end

print() admet dos paràmetres amb nom que en modifiquen el comportament.

sep canvia el separador que es posa entre els arguments. Per defecte és un espai.

print("alta", "mitjana", "baixa")                # alta mitjana baixa
print("alta", "mitjana", "baixa", sep=" / ")     # alta / mitjana / baixa
print("alta", "mitjana", "baixa", sep="")        # altamitjanabaixa
print("2026", "08", "04", sep="-")               # 2026-08-04

Aquest últim exemple és l'ús típic: compondre una data o una ruta sense repetir el separador a mà.

end canvia el que s'imprimeix al final, després de l'últim argument. Per defecte és un salt de línia, "\n"; per això cada print() comença en una línia nova.

print("Carregant", end="")
print(".", end="")
print(".", end="")
print(".", end="")
print(" llest")

Sortida, tota en una sola línia:

Carregant... llest

En posar end="" li dius a print() que no salti de línia, així que la instrucció següent continua on es va quedar l'anterior. És el mecanisme de les barres de progrés i de qualsevol sortida que es construeix per parts.

Combinant totes dues:

print("Marta", "Luis", "Nuria", sep=", ", end=".\n")
Marta, Luis, Nuria.
Paràmetre Valor per defecte Què controla
sep " " (un espai) Què es posa entre els arguments
end "\n" (salt de línia) Què es posa després de l'últim

Els paràmetres amb nom com aquests s'anomenen arguments per paraula clau, i s'estudien a fons a Paràmetres i retorn de valors. De moment n'hi ha prou de saber que s'escriuen nom=valor i que van al final de la crida.

  1. Caràcters d'escapada: \n, \t i les cometes

Dins d'una cadena de text, la barra invertida \ té un significat especial: junt amb el caràcter següent forma una seqüència d'escapada que representa alguna cosa que no es pot teclejar directament.

Escapada Significat Ús típic
\n Salt de línia Diverses línies en un sol print
\t Tabulador Separar columnes
\" Cometa doble literal Cometes dins d'un text entrecometat amb dobles
\' Cometa simple literal Ídem amb simples
\\ Barra invertida literal Rutes de Windows

Salts de línia. Un sol print pot produir diverses línies:

print("FITXA DE TASCA\n----------------\nClient: Forn Sole")
FITXA DE TASCA
----------------
Client: Forn Sole

Tabuladors. \t avança fins a la següent parada de tabulació, cosa que dóna un efecte de columnes:

print("Marta\tcoordinadora")
print("Luis\tdisseny")
print("Nuria\tmaquetacio")
Marta	coordinadora
Luis	disseny
Nuria	maquetacio

Funciona, però amb una limitació important: les parades de tabulació són fixes (normalment cada 8 caràcters), així que si un nom és més llarg que la parada, la columna es desquadra. Per alinear de debò es fan servir els especificadors d'amplada de les f-strings, que veuràs a l'apartat 7.

Cometes dins de text. Hi ha tres maneres de resoldre-ho:

# 1. Cometes diferents per dins i per fora
print("El client va dir: 'ho vull per divendres'")

# 2. Escapant les cometes
print("El client va dir: \"ho vull per divendres\"")

# 3. Cometes simples fora, dobles dins
print('El client va dir: "ho vull per divendres"')

La primera i la tercera són les més llegibles; la segona és útil quan el text conté els dos tipus de cometa.

Barra invertida literal. Com que \ inicia una escapada, per escriure una barra cal duplicar-la:

print("C:\\Usuaris\\marta\\tascafacil")     # C:\Usuaris\marta\tascafacil

Existeix també la cadena crua, que desactiva les escapades: es marca amb una r al davant. És molt pràctica per a rutes de Windows:

print(r"C:\Usuaris\marta\tascafacil")       # C:\Usuaris\marta\tascafacil

I per a textos llargs de diverses línies, les cometes triples conserven el format tal com l'escrius:

print("""
=== TASCAFACIL ===
Gestor de tasques
Estudi Alba
""")

  1. f-strings: interpolació de variables

Arribem a l'eina central d'aquesta lliçó. Una f-string (cadena formatada) és una cadena precedida per la lletra f en la qual pots inserir variables entre claus {}.

responsable = "Luis"
dies_restants = 7

print(f"La tasca es del {responsable} i queden {dies_restants} dies.")
La tasca es del Luis i queden 7 dies.

Compara les tres maneres de fer el mateix:

Forma Codi Problema
Concatenació "La tasca es del " + responsable No admet números sense convertir-los
Arguments de print print("La tasca es del", responsable) Espais automàtics difícils de controlar
f-string f"La tasca es del {responsable}" Cap: es llegeix com el resultat

L'avantatge decisiu de la f-string és que el codi s'assembla al resultat. Veus la frase completa i, a dins, al seu lloc exacte, el buit que ocuparà la dada. I funciona amb qualsevol tipus, sense conversions:

titol = "Logotip Forn Sole"
hores = 9.5
completada = False
data = None

print(f"Tasca: {titol}")              # Tasca: Logotip Forn Sole
print(f"Hores: {hores}")              # Hores: 9.5
print(f"Feta: {completada}")          # Feta: False
print(f"Lliurament: {data}")          # Lliurament: None

La f va enganxada a la cometa d'obertura, i pot anar amb cometes simples, dobles o triples. Si oblides la f, no hi ha error: s'imprimeixen les claus literalment, cosa que és un descuit molt comú.

print("Queden {dies_restants} dies")     # Queden {dies_restants} dies  <- falta la f
print(f"Queden {dies_restants} dies")    # Queden 7 dies

Si necessites una clau literal dins d'una f-string, duplica-la: {{ produeix {.

  1. Expressions dins d'una f-string

Dins de les claus no només hi caben variables: hi cap qualsevol expressió de les que vas aprendre a la lliçó anterior.

hores_dedicades = 9
hores_estimades = 24
dia_actual = 12
dia_lliurament = 19
prioritat = "alta"
completada = False

print(f"Avanc: {hores_dedicades / hores_estimades * 100} %")
print(f"Queden {dia_lliurament - dia_actual} dies")
print(f"Hores per fer: {hores_estimades - hores_dedicades}")
print(f"Urgent: {prioritat == 'alta' and not completada}")
Avanc: 37.5 %
Queden 7 dies
Hores per fer: 15
Urgent: True

Fixa't en l'última línia: dins de les claus hi ha una expressió lògica completa, i a la f-string s'han fet servir cometes simples per a 'alta' perquè les dobles ja estan ocupades per la cadena exterior. Barrejar els dos tipus de cometa és la manera d'evitar el conflicte.

Ara bé, un consell d'estil: que puguis ficar-hi expressions complexes no significa que ho hagis de fer. Aquesta línia és correcta però il·legible:

print(f"{(hores_dedicades / hores_estimades * 100 > 60) and (dia_lliurament - dia_actual < 5)}")

És molt millor calcular abans, amb un nom que expliqui què és, i limitar la f-string a mostrar:

percentatge_avanc = hores_dedicades / hores_estimades * 100
dies_restants = dia_lliurament - dia_actual
va_just = percentatge_avanc > 60 and dies_restants < 5

print(f"Va just de termini: {va_just}")

La regla pràctica: dins d'una f-string, expressions curtes i evidents; la resta, en una variable amb nom.

Un truc útil per depurar: si poses un = després de l'expressió, la f-string mostra també el codi que la va generar.

hores_dedicades = 9
print(f"{hores_dedicades=}")          # hores_dedicades=9

És comodíssim quan estàs buscant per què un valor no és el que esperaves.

  1. Especificadors de format: decimals i alineació

Dins de les claus pots afegir, després de dos punts, un especificador de format que controla com es presenta el valor. La sintaxi general és {valor:format}.

Controlar els decimals

El problema és evident tan bon punt calcules un percentatge:

percentatge = 37.333333333333336
print(f"Avanc: {percentatge} %")            # Avanc: 37.333333333333336 %
print(f"Avanc: {percentatge:.2f} %")        # Avanc: 37.33 %
print(f"Avanc: {percentatge:.1f} %")        # Avanc: 37.3 %
print(f"Avanc: {percentatge:.0f} %")        # Avanc: 37 %

.2f significa «format de coma flotant amb 2 decimals». Arrodoneix, no trunca: 37.336 amb .2f dóna 37.34.

És l'especificador que més faràs servir. Qualsevol quantitat calculada amb / que s'hagi de mostrar a una persona n'hauria de portar.

Alinear en columnes

Aquí és on les f-strings superen definitivament el tabulador \t. Pots fixar una amplada mínima i una alineació:

Especificador Significat Exemple amb "Luis"
{text:<10} Alinea a l'esquerra en 10 caràcters Luis______
{text:>10} Alinea a la dreta en 10 caràcters ______Luis
{text:^10} Centra en 10 caràcters ___Luis___
{text:<10} amb farciment {text:.<10} omple amb punts Luis......

(Els guions baixos representen espais.)

Vegem-ho component una taula de l'equip d'Estudi Alba:

print(f"{'RESPONSABLE':<12}{'TASQUES':>8}{'HORES':>8}")
print("-" * 28)
print(f"{'Marta':<12}{3:>8}{12.5:>8}")
print(f"{'Luis':<12}{5:>8}{27.0:>8}")
print(f"{'Nuria':<12}{2:>8}{9.25:>8}")
RESPONSABLE  TASQUES   HORES
----------------------------
Marta              3    12.5
Luis               5    27.0
Nuria              2    9.25

El text s'alinea a l'esquerra (<) perquè així es llegeixen les paraules; els números a la dreta (>) perquè així s'alineen les unitats, les desenes i les centenes. És la convenció de qualsevol taula ben feta.

I es poden combinar amplada i decimals, posant l'amplada primer i la precisió després:

print(f"{'Marta':<12}{12.5:>8.2f}")
print(f"{'Luis':<12}{27.0:>8.2f}")
print(f"{'Nuria':<12}{9.25:>8.2f}")
Marta          12.50
Luis           27.00
Nuria           9.25

Ara sí: columna perfecta, amb dos decimals en tots els casos.

Especificador Què fa
{x:.2f} 2 decimals
{x:>8} Amplada 8, alineat a la dreta
{x:<15} Amplada 15, alineat a l'esquerra
{x:^20} Amplada 20, centrat
{x:>10.2f} Amplada 10, a la dreta, 2 decimals
{x:,} Separador de milers: 1250000 → 1,250,000
{x:.1%} Com a percentatge: 0.375 → 37.5%

Aquest últim mereix una nota: {0.375:.1%} multiplica per 100 i afegeix el símbol. Si el teu valor ja és en escala 0-100, fes servir .1f i escriu el % tu.

  1. Altres maneres de formatar que veuràs en codi aliè

Les f-strings existeixen des de Python 3.6 i són la forma recomanada avui. Però trobaràs codi —tutorials antics, projectes heretats— escrit amb les dues formes anteriors, i convé reconèixer-les.

El mètode .format(), de Python 3.0 endavant:

responsable = "Luis"
dies = 7

print("La tasca es del {} i queden {} dies.".format(responsable, dies))
print("La tasca es del {0} i queden {1} dies.".format(responsable, dies))
print("Avanc: {:.2f} %".format(37.333))

Els buits {} s'omplen en ordre amb els arguments de .format(). Els especificadors després dels dos punts són els mateixos que a les f-strings, així que l'après a l'apartat anterior et serveix igual.

L'operador %, heretat del llenguatge C i encara present en molt codi antic:

print("La tasca es del %s i queden %d dies." % (responsable, dies))
print("Avanc: %.2f %%" % 37.333)

Aquí %s és un buit per a text, %d per a enter i %.2f per a decimal amb dues xifres. És el més críptic dels tres i el més propens a errors.

Forma Aspecte Quan fer-la servir
f-string f"Hola {nom}" Sempre, en codi nou
.format() "Hola {}".format(nom) Només si mantens codi antic
% "Hola %s" % nom Mai en codi nou; reconèixer-lo n'hi ha prou

Queda't amb això: escriu f-strings, i si topes amb les altres dues, ja saps què fan.

  1. input(): demanar dades per teclat

input() és la funció que atura el programa i espera que l'usuari teclegi alguna cosa i premi Intro.

responsable = input()
print(responsable)

Aquest programa es queda esperant sense dir res, cosa que és una pèssima experiència d'ús. Per això input() admet un argument: el missatge d'indicació o prompt, que es mostra abans d'esperar.

responsable = input("Responsable de la tasca: ")
print(f"Tasca assignada a {responsable}")

Execució (el que teclega l'usuari va subratllat pel cursor, aquí ho marquem a part):

Responsable de la tasca: Nuria
Tasca assignada a Nuria

El funcionament pas a pas:

flowchart TD
    A["El programa arriba a input()"] --> B["Mostra el missatge del prompt"]
    B --> C["S'ATURA i espera"]
    C --> D["L'usuari tecleja i prem Intro"]
    D --> E["input() retorna el que ha teclejat<br/>com a text"]
    E --> F["Aquest text s'assigna a la variable"]

Tres detalls d'ús que marquen la diferència:

1. Acaba el prompt amb espai o dos punts i espai. Sense això, el que teclegi l'usuari apareixerà enganxat al missatge:

nom = input("Responsable:")       # Responsable:Nuria   <- lleig
nom = input("Responsable: ")      # Responsable: Nuria  <- correcte

2. Digues exactament què esperes. Un prompt vague genera dades inservibles:

prioritat = input("Prioritat: ")                           # l'usuari no sap que posar
prioritat = input("Prioritat (alta/mitjana/baixa): ")      # molt millor

3. El resultat s'ha de desar. Escriure input("Nom: ") sense assignar-ho a res demana la dada i la llença. És un descuit habitual.

I una conseqüència que es nota en executar: input() bloqueja el programa. Res més no passa fins que l'usuari prem Intro. Si el teu programa sembla «penjat», comprova si està esperant una entrada.

  1. El punt capital: input() sempre retorna text

Aquí hi ha la idea més important de la lliçó, i convé que la llegeixis dues vegades:

input() retorna SEMPRE un valor de tipus str, sense excepcions, encara que l'usuari teclegi un número.

Comprova-ho:

dies = input("Dies estimats: ")

print(dies)          # 3
print(type(dies))    # <class 'str'>   <- NO es int

L'usuari ha teclejat 3, a la pantalla es veu 3, però el que hi ha desat és el text "3", no el número 3. I això té conseqüències immediates i desconcertants:

dies = input("Dies estimats: ")      # l'usuari tecleja 3

print(dies * 2)      # 33     <- repeteix el text, no multiplica!

"3" * 2 és repetició de cadena, que ja vas veure a la lliçó anterior: produeix "33". No és una fallada de Python; és que estàs multiplicant text.

I si intentes aritmètica de debò, el programa s'atura:

dies = input("Dies estimats: ")      # l'usuari tecleja 3

print(dies + 1)
TypeError: can only concatenate str (not "int") to str

És el mateix TypeError de la lliçó anterior, vist ara des de l'altre costat. Resumim què passa segons el que s'intenti:

Operació amb dies = input() (l'usuari tecleja 3) Resultat
print(dies) Mostra 3 — sembla un número
type(dies) <class 'str'> — no ho és
dies + 1 TypeError
dies * 2 "33" (repetició, no multiplicació)
dies > 2 TypeError — no es pot comparar text amb número
f"Dies: {dies}" Dies: 3 — funciona, perquè només es mostra

Fixa't en l'última fila: mostrar la dada funciona perfectament. El problema apareix només quan vols calcular amb ella.

Per això, a l'aplicació d'aquesta lliçó, TascaFàcil demanarà únicament dades que són text per naturalesa —títol, responsable, prioritat— i no demanarà els dies estimats ni les hores. Tan bon punt calgui un número, l'haurem de convertir, i aquesta conversió, juntament amb el que passa si l'usuari teclega «tres» en lloc de «3», és exactament el contingut de Conversió de tipus i validació.

Deixem, doncs, dos caps solts anotats:

  • input() retorna text i de vegades necessitem números.
  • L'usuari pot escriure "ALTA", " alta " o "urgent", i cap dels tres no coincideix amb "alta" (aquell descobriment de la prova d'escriptori de 01-05).

Tots dos es lliguen a la propera lliçó.

  1. TascaFàcil: la fitxa es demana i es presenta

Versió 0.4 de tascafacil.py. El programa demana per teclat les tres dades de text de la tasca i mostra una fitxa alineada en columnes amb f-strings. Les dades numèriques continuen al codi, a l'espera de saber-les convertir.

# tascafacil.py - Estudi Alba
# Versio 0.4: les dades de text es demanen per teclat
#             i la fitxa es presenta amb f-strings

NOM_APP = "TascaFacil"
VERSIO = "0.4"
ESTUDI = "Estudi Alba"
AMPLE = 46
HORES_PER_JORNADA = 8

# --- Capcalera ---
print("=" * AMPLE)
print(f"{NOM_APP + ' v' + VERSIO:^{AMPLE}}")
print(f"{'Gestor de tasques - ' + ESTUDI:^{AMPLE}}")
print("=" * AMPLE)
print()

# --- ENTRADA: dades que teclega l'usuari ---
print("Introdueix les dades de la tasca:")
print()

titol = input("  Titol                        : ")
descripcio = input("  Descripcio                   : ")
responsable = input("  Responsable (Marta/Luis/Nuria): ")
prioritat = input("  Prioritat (alta/mitjana/baixa): ")

# --- Dades que encara no podem demanar (son numeros) ---
dia_actual = 12
dia_lliurament = 19
hores_estimades = 24
hores_dedicades = 9
completada = False

# --- PROCES: calculs amb les dades ---
dies_restants = dia_lliurament - dia_actual
percentatge_avanc = hores_dedicades / hores_estimades * 100
hores_restants = hores_estimades - hores_dedicades
jornades_restants = hores_restants / HORES_PER_JORNADA
es_urgent = prioritat == "alta" and not completada

# --- SORTIDA: fitxa alineada ---
print()
print("=" * AMPLE)
print(f"{'FITXA DE TASCA':^{AMPLE}}")
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"{'Completada':<16}{str(completada):>{AMPLE - 16}}")
print("-" * AMPLE)
print(f"{'Dies restants':<16}{dies_restants:>{AMPLE - 16}}")
print(f"{'Hores fetes':<16}{hores_dedicades:>{AMPLE - 16}.1f}")
print(f"{'Hores totals':<16}{hores_estimades:>{AMPLE - 16}.1f}")
print(f"{'Avanc':<16}{percentatge_avanc:>{AMPLE - 18}.1f} %")
print(f"{'Jornades rest.':<16}{jornades_restants:>{AMPLE - 16}.2f}")
print("-" * AMPLE)
print(f"{'Urgent':<16}{str(es_urgent):>{AMPLE - 16}}")
print("=" * AMPLE)
print()
print(f"Descripcio: {descripcio}")

Una execució completa, amb la Marta registrant l'encàrrec del client Vidal:

==============================================
               TascaFacil v0.4
       Gestor de tasques - Estudi Alba
==============================================

Introdueix les dades de la tasca:

  Titol                        : Targetes de visita Vidal
  Descripcio                   : 300 uts, doble cara, paper reciclat
  Responsable (Marta/Luis/Nuria): Nuria
  Prioritat (alta/mitjana/baixa): alta

==============================================
                FITXA DE TASCA
==============================================
Titol                 Targetes de visita Vidal
Responsable                              Nuria
Prioritat                                 alta
Completada                               False
----------------------------------------------
Dies restants                                7
Hores fetes                                9.0
Hores totals                              24.0
Avanc                                   37.5 %
Jornades rest.                            1.88
----------------------------------------------
Urgent                                    True
==============================================

Descripcio: 300 uts, doble cara, paper reciclat

Repassem les tècniques emprades, perquè l'exemple condensa tota la lliçó:

  • "=" * AMPLE dibuixa els separadors. És la repetició de cadenes de la lliçó anterior, aquí amb un ús molt pràctic.
  • {text:^{AMPLE}} centra el títol en l'amplada total. Fixa't en el detall avançat: l'amplada no està escrita a mà, és una altra variable entre claus. Així, canviant AMPLE a la primera línia, tota la fitxa es reajusta.
  • {'Titol':<16} reserva 16 caràcters per a l'etiqueta, alineada a l'esquerra.
  • {titol:>{AMPLE - 16}} ocupa la resta de la línia amb el valor alineat a la dreta. Dins de les claus d'amplada hi ha una expressió, AMPLE - 16, perfectament vàlida.
  • {percentatge_avanc:>{AMPLE - 18}.1f} % combina amplada, alineació i un decimal; el - 18 en comptes de - 16 deixa lloc per als dos caràcters del % que van al darrere, de manera que la línia continua mesurant exactament AMPLE.
  • str(completada) converteix el booleà a text. És necessari perquè els especificadors d'alineació < i > funcionen de manera diferent amb booleans que amb cadenes; convertint-lo primer, s'alinea com qualsevol altre text. La funció str() és, precisament, el primer que veuràs a la propera lliçó.

El que continua sense funcionar

Prova aquesta execució i observa el resultat:

  Responsable (Marta/Luis/Nuria): NURIA
  Prioritat (alta/mitjana/baixa): ALTA

La fitxa es genera igual de bonica, però a sota hi diu Urgent False. La comparació prioritat == "alta" ha fallat perquè l'usuari va escriure en majúscules. I si escriu urgentissima, o deixa el camp en blanc prement Intro, el programa tampoc no protesta: desa la brossa i continua.

Aquesta és exactament la feina pendent.

Errors Comuns i Consells

Oblidar la f de la f-string. print("Queden {dies} dies") imprimeix les claus tal qual. No dóna error, així que cal veure-ho a la sortida. Si veus claus a la pantalla, falta la f.

Fer servir cometes dobles dins d'una f-string delimitada per dobles. f"Es {x == "alta"}" trenca la cadena. Fes servir cometes simples a dins: f"Es {x == 'alta'}".

Confondre .2f amb «dos dígits». .2f són dos decimals, no dues xifres en total. Per a l'amplada total es fa servir el número abans del punt: {x:8.2f}.

Alinear números a l'esquerra. Queda desalineat i costa comparar magnituds. Text a l'esquerra (<), números a la dreta (>).

Confiar en \t per fer taules. Funciona mentre tots els valors mesurin menys que la parada de tabulació; tan bon punt un se'n passa, la columna es desquadra. Fes servir amplades explícites.

No assignar el resultat d'input(). input("Nom: ") sense variable = al davant demana la dada i la descarta.

Prompt sense espai final. input("Nom:") fa que el que es teclegi s'enganxi al missatge. Deixa sempre un espai.

Donar per fet que input() retorna un número. És l'error que defineix aquesta lliçó: sempre retorna str. Si has de calcular, hauràs de convertir.

Prompts que no expliquen les opcions. Si només s'admeten tres prioritats, escriu-les al prompt. El cost d'un prompt clar és zero i estalvia la meitat de les entrades errònies.

Consell: separa entrada, procés i sortida. Mira l'estructura del programa d'aquesta lliçó: primer tots els input(), després tots els càlculs, i al final tota la presentació. És més fàcil de llegir, de provar i de modificar que si estan entremesclats. Aquesta separació és un principi de disseny que es manté en programes de qualsevol mida.

Consell: defineix l'amplada com a constant. AMPLE = 46 en lloc de repetir 46 en quinze línies. Canviar el disseny de la fitxa passa a ser qüestió d'una línia.

Consell: prova amb dades incòmodes. Executa el teu programa i teclega un títol llarguíssim, o prem Intro sense escriure res. La fitxa es desquadrarà o quedarà buida. Anota el que has vist: això és el que cal validar.

Exercicis

Exercici 1: Predir la sortida

Escriu exactament què imprimeix cada bloc, parant atenció a espais i salts de línia.

# a)
print("Marta", "Luis", "Nuria", sep=" | ")

# b)
print("Tasca", end=" -> ")
print("completada")

# c)
hores = 7.456
print(f"{hores:.2f}")
print(f"{hores:.0f}")

# d)
nom = "Luis"
print(f"[{nom:<10}]")
print(f"[{nom:>10}]")
print(f"[{nom:^10}]")

# e)
print("Linia 1\n\tLinia 2 tabulada")

# f)
dies = 5
print("Queden {dies} dies")
print(f"Queden {dies} dies")

# g)
print(f"{'Total':<8}{1250:>10,}")

Exercici 2: Fitxa de l'equip d'Estudi Alba

Escriu un programa resum_equip.py que mostri aquesta taula fent servir només f-strings (res de \t), amb aquestes dades ja escrites en variables:

Persona Tasques pendents Hores dedicades Percentatge de càrrega
Marta 3 12.5 0.25
Luis 5 27.0 0.45
Nuria 2 9.25 0.30

Requisits:

  • Capçalera centrada en una amplada de 44 caràcters, amb línies de = a dalt i a baix.
  • Noms alineats a l'esquerra; números a la dreta.
  • Hores amb un decimal; el percentatge de càrrega mostrat com a percentatge amb un decimal (recorda {x:.1%}).
  • L'amplada total ha d'estar en una constant i fer-se servir a totes les línies.

Exercici 3: Registre interactiu de tasca

Escriu registre_tasca.py que:

  1. Mostri una capçalera de benvinguda.
  2. Demani per teclat, amb prompts clars: títol, client, responsable i prioritat.
  3. Mostri una fitxa amb les quatre dades alineades en dues columnes.
  4. Al final, mostri en una sola línia, fent servir una f-string amb una expressió a dins, si la tasca és de prioritat alta.
  5. Imprimeixi el type() de la variable prioritat i expliqui en un comentari què significa el resultat.

Solucions

Solució 1.

a) Marta | Luis | Nuria — el sep substitueix l'espai per " | ".

b)

Tasca -> completada

Una sola línia: el primer print no salta perquè end=" -> ".

c)

7.46
7

.2f arrodoneix a dos decimals (7.456 → 7.46) i .0f a zero decimals (7.456 → 7).

d)

[Luis      ]
[      Luis]
[   Luis   ]

Deu caràcters d'amplada en els tres casos; canvia on es col·loca el text. En centrar amb amplada sobrant senar, el buit extra va a la dreta.

e)

Linia 1
	Linia 2 tabulada

\n salta de línia i \t fica un tabulador al principi de la segona.

f)

Queden {dies} dies
Queden 5 dies

Sense la f, les claus són text literal. És el descuit més comú.

g) Total 1,250 — Total ocupa 8 caràcters a l'esquerra, i 1250 es mostra amb separador de milers en 10 caràcters a la dreta.

Solució 2.

# resum_equip.py - Estudi Alba

AMPLE = 44

marta_tasques = 3
marta_hores = 12.5
marta_carrega = 0.25

luis_tasques = 5
luis_hores = 27.0
luis_carrega = 0.45

nuria_tasques = 2
nuria_hores = 9.25
nuria_carrega = 0.30

print("=" * AMPLE)
print(f"{'RESUM PER RESPONSABLE - Estudi Alba':^{AMPLE}}")
print("=" * AMPLE)
print(f"{'PERSONA':<14}{'TASQUES':>8}{'HORES':>11}{'CARREGA':>11}")
print("-" * AMPLE)
print(f"{'Marta':<14}{marta_tasques:>8}{marta_hores:>11.1f}{marta_carrega:>11.1%}")
print(f"{'Luis':<14}{luis_tasques:>8}{luis_hores:>11.1f}{luis_carrega:>11.1%}")
print(f"{'Nuria':<14}{nuria_tasques:>8}{nuria_hores:>11.1f}{nuria_carrega:>11.1%}")
print("=" * AMPLE)

Sortida:

============================================
    RESUM PER RESPONSABLE - Estudi Alba
============================================
PERSONA        TASQUES      HORES    CARREGA
--------------------------------------------
Marta                3       12.5      25.0%
Luis                 5       27.0      45.0%
Nuria                2        9.2      30.0%
============================================

Fixa't en les amplades escollides: 14 + 8 + 11 + 11 = 44, exactament AMPLE. Quan les columnes sumen l'amplada total, les línies de = i - encaixen amb la taula i el resultat sembla fet expressament, que és justament el que busquem.

Observa també que 9.25 amb .1f es mostra com a 9.2 i no com a 9.3: davant d'un empat exacte, Python arrodoneix al dígit parell més proper (l'anomenat arrodoniment bancari). No és un error, però convé saber-ho quan presentis xifres a un client.

Solució 3.

# registre_tasca.py - Estudi Alba

AMPLE = 44

print("=" * AMPLE)
print(f"{'REGISTRE DE NOVA TASCA':^{AMPLE}}")
print(f"{'Estudi Alba':^{AMPLE}}")
print("=" * AMPLE)
print()

titol = input("Titol de la tasca             : ")
client = input("Client                        : ")
responsable = input("Responsable (Marta/Luis/Nuria): ")
prioritat = input("Prioritat (alta/mitjana/baixa): ")

print()
print("-" * AMPLE)
print(f"{'FITXA':^{AMPLE}}")
print("-" * AMPLE)
print(f"{'Titol':<14}{titol:>{AMPLE - 14}}")
print(f"{'Client':<14}{client:>{AMPLE - 14}}")
print(f"{'Responsable':<14}{responsable:>{AMPLE - 14}}")
print(f"{'Prioritat':<14}{prioritat:>{AMPLE - 14}}")
print("-" * AMPLE)

print(f"Es de prioritat alta: {prioritat == 'alta'}")

# <class 'str'>: input() retorna SEMPRE text, encara que l'usuari
# teclegi un numero. Per aixo la comparacio de dalt nomes funciona
# si escriu exactament "alta" en minuscules.
print(type(prioritat))

Exemple d'execució:

============================================
           REGISTRE DE NOVA TASCA
                Estudi Alba
============================================

Titol de la tasca             : Cartell fira del llibre
Client                        : Associacio de llibreters
Responsable (Marta/Luis/Nuria): Nuria
Prioritat (alta/mitjana/baixa): mitjana

--------------------------------------------
                   FITXA
--------------------------------------------
Titol                Cartell fira del llibre
Client              Associacio de llibreters
Responsable                            Nuria
Prioritat                            mitjana
--------------------------------------------
Es de prioritat alta: False
<class 'str'>

Prova d'executar-lo de nou escrivint ALTA a la prioritat: la fitxa sortirà igual de correcta, però Es de prioritat alta continuarà dient False. Aquest és el problema que resolem tot seguit.

Conclusió

El teu programa ja parla amb el món. Saps que print() accepta diversos arguments separats per comes —convertint cadascun a text automàticament— i que els seus paràmetres sep i end controlen què es posa entre els valors i què es posa al final. Manegues els caràcters d'escapada \n, \t, \" i \\, i saps resoldre les cometes dins d'un text de tres maneres diferents.

Sobretot, domines les f-strings: interpolar variables i expressions entre claus, arrodonir decimals amb .2f, i alinear columnes amb <, > i ^ per produir taules llegibles sense dependre del tabulador. Reconeixes a més .format() i l'antic % quan els trobis en codi aliè, encara que escriguis sempre f-strings.

I coneixes input(): com atura el programa, com se li posa un missatge útil i —el punt que governa la propera lliçó— que retorna sempre un str, encara que l'usuari teclegi un número.

TascaFàcil és a la seva versió 0.4 i ja s'assembla a una eina: la Marta l'executa, teclega el títol, la descripció, el responsable i la prioritat de l'encàrrec, i obté una fitxa alineada amb els càlculs de termini i avanç. Ningú no ha d'obrir l'editor per registrar una tasca nova.

Però hem deixat dos caps solts ben visibles. El primer: les dades numèriques —dies estimats, hores dedicades— continuen escrites al codi, perquè el que arriba d'input() és text i "3" + 1 dóna TypeError. El segon: el programa s'empassa qualsevol cosa que li teclegi l'usuari. Si la Marta escriu ALTA, la comparació falla; si escriu urgentissima, es desa tal qual; si prem Intro sense escriure, la tasca es queda sense títol.

Tots dos són el mateix problema vist de dues maneres: les dades que vénen de fora no són de fiar. A Conversió de tipus i validació aprendràs a convertir-les al tipus correcte amb int(), float() i str(), a sanejar-les amb .strip() i .lower() —cosa que per fi farà que "ALTA" valgui tant com "alta", el cap que vam deixar solt a la lliçó 01-05— i a comprovar que són vàlides abans de fer-les servir. Amb això tancarem el mòdul 2 i TascaFàcil serà, per primera vegada, un programa robust.

© Copyright 2026. Tots els drets reservats