Ja tens les tres eines: saps definir i cridar funcions (04-01), saps donar-los paràmetres i fer que retornin valors (04-02), i saps de què han de dependre per ser peces autònomes (04-03). El que falta és el criteri: davant d'un programa de cent línies escrites d'una tirada, per on es talla? Quantes funcions? De quina mida? Què va dins de cadascuna?

Aquesta pregunta no té una resposta mecànica, però sí que té criteris sòlids i comprovables, i aquesta lliçó els recorre un a un. Al final els aplicarem al cas que arrosseguem des del mòdul 3: convertir el mur monolític de tascafacil.py v0.6 en la versió 0.7, un programa organitzat en funcions amb un main() que es llegeix en vint segons. El que farem té nom propi: refactoritzar, és a dir, reorganitzar el codi sense canviar el que fa. En acabar, TascaFàcil es comportarà exactament igual de cara a l'usuari; el que canvia és tota la resta, la facilitat per entendre'l, corregir-lo i ampliar-lo.

Contingut

  1. Una funció, una responsabilitat
  2. Mida i nivell d'abstracció
  3. Disseny descendent: escriure el main() primer
  4. L'arbre de crides
  5. Separar entrada/sortida de lògica
  6. Noms que descriuen l'efecte
  7. DRY i l'excés contrari
  8. El bloc if __name__ == "__main__":
  9. TascaFàcil v0.7: la refactorització completa
  10. Errors comuns i consells
  11. Exercicis
  12. Conclusió

  1. Una funció, una responsabilitat

El criteri principal és aquest: una funció ha de fer una sola cosa i fer-la sencera. La prova pràctica consisteix a descriure-la en una frase curta, sense conjuncions. Si necessites una «i», tens dues funcions.

Descripció de la funció Veredicte
«Demana un enter entre dos límits» Una responsabilitat
«Pinta la fitxa d'una tasca» Una responsabilitat
«Demana les dades i les desa i avisa per pantalla» Tres responsabilitats
«Valida el títol i actualitza l'estat» Dues responsabilitats

L'avantatge de respectar-ho no és estètic, és econòmic. Una funció amb una sola responsabilitat té una sola raó per canviar. El dia que Estudi Alba decideixi acceptar dies amb decimals, toques demanar_enter i res més. Si aquesta mateixa funció també pintés la fitxa, canviar el format de la fitxa t'obligaria a tocar codi de validació, amb el risc de trencar-lo sense adonar-te'n.

  1. Mida i nivell d'abstracció

De la regla anterior se'n deriva una mida típica: entre tres i vint línies. No és una llei, és una conseqüència: una funció que ocupa seixanta línies gairebé sempre està fent diverses coses. I hi ha un senyal molt fiable que se n'ha passat: si per explicar-la a algú has de dir «primer fa això, després això altre, i al final allò», aquests tres passos volen ser tres funcions. El segon criteri, més subtil però molt potent, és el nivell d'abstracció homogeni: dins d'una mateixa funció, totes les línies haurien d'explicar la història a la mateixa altura. Compara aquestes dues versions del mateix:

def processar_tasca():                           # nivells BARREJATS
    titol, responsable, prioritat, dies = registrar_tasca()   # alt nivell
    print("=" * 46)                              # baix nivell
    print(f"{'Titol':<14}{titol:>32}")           # baix nivell
    print("-" * 46)                              # baix nivell

def processar_tasca():                           # nivell HOMOGENI
    titol, responsable, prioritat, dies = registrar_tasca()
    mostrar_fitxa(titol, responsable, prioritat, dies, False)
    pausar()

La segona es llegeix com un resum del que passa; la primera obliga a llegir codi de formatatge per assabentar-te de la trama. La regla mnemotècnica: una funció s'ha de llegir com un índex, no com una novel·la.

  1. Disseny descendent: escriure el main() primer

El disseny descendent (top-down) consisteix a escriure primer el programa principal com si les funcions que necessites ja existissin, i només després implementar-les. És contraintuïtiu i funciona sorprenentment bé, perquè t'obliga a decidir què necessites abans de perdre't en el com:

def main():
    """Bucle principal de l'aplicacio."""
    while True:
        mostrar_menu()
        opcio = demanar_opcio("Tria una opcio (1-5): ", OPCIONS)
        if opcio == "1":
            registrar_tasca()
        elif opcio == "5":
            break
        pausar()

Cap d'aquestes funcions no existeix encara, i tanmateix ja has pres les decisions importants: quantes peces hi ha, com es diuen i què rep cadascuna. Aquest esbós és alhora un pla de treball i una llista de tasques. El truc pràctic per no bloquejar-te és omplir els buits amb funcions buides que només tinguin un pass o un print provisional. Així el programa s'executa des del primer minut i pots anar substituint aquests esquelets per implementacions reals d'una en una, comprovant després de cada pas. És molt millor que escriure-ho tot i executar-ho per primera vegada al final, quan qualsevol error pot ser a qualsevol lloc.

  1. L'arbre de crides

En descompondre apareix una estructura en capes: el main() crida funcions d'acció i aquestes criden funcions auxiliars. Dibuixar-la ajuda a detectar desequilibris:

flowchart TD
    M["main()"] --> MM["mostrar_menu() i pausar()"]
    M --> PO["demanar_opcio()"]
    M --> RT["registrar_tasca()"]
    M --> MF["mostrar_fitxa()"]
    M --> CP["canviar_prioritat()"]
    M --> MC["marcar_completada()"]
    RT --> PT["demanar_text()"]
    RT --> PO
    RT --> PE["demanar_enter()"]
    CP --> PO
    MF --> CU["classificar_urgencia()"]
    MC --> CF["confirmar()"]

Tres coses que aquest arbre t'explica d'una ullada. Primer, que hi ha dos nivells clars: accions a dalt i utilitats a baix. Segon, que demanar_opcio la fan servir tres funcions diferents: és la peça més reutilitzada del programa, i això confirma que valia la pena extreure-la. I tercer, que cap branca no baixa més de tres nivells, senyal que el programa no està sobrefragmentat.

  1. Separar entrada/sortida de lògica

Aquesta és la regla que més millora un programa per línia d'esforç: les funcions que calculen no imprimeixen ni pregunten. La feina es reparteix en tres famílies:

Família Què fa Exemples a TascaFàcil
Entrada Pregunta a l'usuari i valida demanar_text, demanar_enter, confirmar
Lògica Calcula i decideix, en silenci classificar_urgencia
Sortida Presenta resultats mostrar_menu, mostrar_fitxa

Per què importa tant? Perquè una funció de lògica pura és comprovable: li dones unes entrades, mires el valor retornat i saps si està bé, sense teclejar res ni mirar la pantalla. classificar_urgencia("alta", 2) ha de retornar "CRITICA", i això es pot verificar mil vegades en un segon; si aquella funció imprimís en comptes de retornar, l'única manera de comprovar-la seria executar l'aplicació i llegir amb els ulls. Aquesta idea és la base de les proves automatitzades. Hi ha a més un benefici més immediat: si demà TascaFàcil passa a tenir interfície gràfica o a generar un informe en un fitxer, tota la lògica se salva i només canvien les funcions d'entrada i sortida.

  1. Noms que descriuen l'efecte

El nom d'una funció és un contracte amb qui la llegeix, i hi ha quatre senyals fàcils d'aplicar. La primera són els prefixos: mostrar_* imprimeix i no retorna res útil, obtenir_* o calcular_* retornen i no imprimeixen, demanar_* pregunta a l'usuari; complir-los fa que el lector encerti sense obrir la funció. La segona: els noms amb «i» delaten dues responsabilitats, així que validar_i_desar() no és un nom llarg sinó un diagnòstic —parteix-la en validar() i desar(). La tercera: evita noms genèrics com processar, gestionar o dades, perquè si no trobes un nom concret sol ser que la funció no té un propòsit concret. I la quarta: el nom ha d'advertir dels efectes; una funció anomenada calcular_total que a més posa a zero un comptador està mentint, i qui la faci servir s'endurà una sorpresa desagradable.

  1. DRY i l'excés contrari

DRYDon't Repeat Yourself, no et repeteixis— és el principi que diu que cada peça de coneixement ha d'estar en un sol lloc del programa. És el que apliquem des de 04-01. La manera pràctica d'aplicar-lo és preguntar-se, davant de dos trossos semblants, en què es diferencien. Si la diferència és un valor —un missatge, un rang, un catàleg—, aquest valor vol ser un paràmetre i els dos trossos volen ser una funció; si la diferència és estructural, potser no són el mateix i forçar-ne la unió els empitjora tots dos. Perquè també existeix l'excés contrari, la sobrefragmentació: partir en funcions diminutes que no aporten res, com un def sumar_un(n): return n + 1 o un def es_zero(n): return n == 0. Aquestes funcions allarguen el programa i obliguen el lector a saltar d'un lloc a l'altre per descobrir que feien l'obvi. Una funció mereix existir si es compleix almenys una d'aquestes tres condicions: es fa servir més d'una vegada, el seu nom explica alguna cosa que el codi no diu per si sol, o amaga una complexitat que embrutaria qui la crida. classificar_urgencia compleix la segona; demanar_enter compleix les tres; sumar_un no en compleix cap.

  1. El bloc if __name__ == "__main__":

Hauràs vist aquestes dues línies al final de gairebé qualsevol programa Python, després de totes les definicions:

if __name__ == "__main__":
    main()

__name__ és una variable que Python crea automàticament a cada fitxer. Quan el fitxer s'executa directament (python tascafacil.py), el seu __name__ val "__main__" i la condició es compleix, així que main() arrenca. Quan el fitxer s'importa des d'un altre per aprofitar-ne les funcions, __name__ val en canvi el nom del fitxer ("tascafacil"), la condició és falsa i l'aplicació no es llança sola. Això és el que vols: poder reutilitzar classificar_urgencia des d'un altre programa sense que se t'obri el menú per sorpresa. La teoria completa de la importació és Mòduls, paquets i importacions; de moment adopta la forma, que és sempre la mateixa: defineix main(), posa-la al final al costat de les altres definicions, i tanca el fitxer amb aquest bloc de dues línies.

  1. TascaFàcil v0.7: la refactorització completa

Recordem el punt de partida. La v0.6 era un únic bloc de gairebé cent línies seguides, amb aquesta forma:

# v0.6 (abreujat): tot en un sol bloc
hi_ha_tasca = False                    # i cinc variables mes d'estat
while True:
    print("\n" + "=" * AMPLE)          # 8 linies seguides de menu
    opcio = input("Tria una opcio (1-5): ").strip()
    while opcio not in OPCIONS:        # validacio de l'opcio
        opcio = input("Opcio no valida. Tria 1-5: ").strip()
    if opcio == "1":
        ...                            # 15 linies: confirmacio + QUATRE validacions
    elif opcio == "2":
        if not hi_ha_tasca:            # comprovacio repetida (1 de 3)
            ...
    elif opcio == "3":
        if not hi_ha_tasca:            # repetida (2 de 3) + validacio duplicada
            ...
    elif opcio == "4":
        if not hi_ha_tasca:            # comprovacio repetida (3 de 3)
            ...
    input("\nPrem Intro per tornar al menu...")

I aquí tens la v0.7 completa, amb les funcions agrupades per famílies:

# tascafacil.py - Estudi Alba
# Versio 0.7: programa descompost en funcions

AMPLE = 46
PRIORITATS = ("alta", "mitjana", "baixa")
EQUIP = ("marta", "luis", "nuria")
OPCIONS = ("1", "2", "3", "4", "5")

# --- Entrada: pregunten i validen ---
def demanar_text(missatge, obligatori=True):
    """Demana un text i el retorna sense espais sobrants."""
    valor = input(missatge).strip()
    while obligatori and valor == "":
        valor = input("No pot estar buit. " + missatge).strip()
    return valor

def demanar_opcio(missatge, opcions):
    """Demana un valor fins que sigui dins de les opcions admeses."""
    valor = input(missatge).strip().lower()
    while valor not in opcions:
        valor = input(f"No valid. Admesos: {', '.join(opcions)}. ").strip().lower()
    return valor

def demanar_enter(missatge, minim, maxim):
    """Demana un enter del rang indicat i el retorna ja convertit."""
    text = input(missatge).strip()
    while not text.isdigit() or not minim <= int(text) <= maxim:
        text = input(f"Enter entre {minim} i {maxim}. ").strip()
    return int(text)

def confirmar(missatge):
    """Retorna True nomes si l'usuari respon 's'."""
    return input(f"{missatge} (s/n): ").strip().lower() == "s"

# --- Logica: calcula, no imprimeix ---
def classificar_urgencia(prioritat, dies):
    """Retorna l'etiqueta d'urgencia que correspon a la tasca."""
    if prioritat == "alta" and dies <= 2:
        return "CRITICA"
    if prioritat == "alta":
        return "Urgent"
    if prioritat == "mitjana" and dies <= 3:
        return "Atencio"
    return "Normal"

# --- Sortida: imprimeixen, no calculen ---
def mostrar_menu():
    """Pinta la capcalera i les cinc opcions disponibles."""
    print("\n" + "=" * AMPLE)
    print(f"{'TascaFacil v0.7 - Estudi Alba':^{AMPLE}}")
    print("=" * AMPLE)
    print(" 1. Registrar / substituir la tasca")
    print(" 2. Veure la fitxa de la tasca")
    print(" 3. Canviar la prioritat")
    print(" 4. Marcar com a completada")
    print(" 5. Sortir")
    print("-" * AMPLE)

def mostrar_fitxa(titol, responsable, prioritat, dies, completada):
    """Pinta la fitxa completa de la tasca indicada."""
    estat = "Completada" if completada else "Pendent"
    print("-" * AMPLE)
    print(f"{'Titol':<14}{titol:>{AMPLE - 14}}")
    print(f"{'Responsable':<14}{f'{responsable} ({prioritat})':>{AMPLE - 14}}")
    print(f"{'Dies / estat':<14}{f'{dies} / {estat}':>{AMPLE - 14}}")
    print(f"{'Urgencia':<14}{classificar_urgencia(prioritat, dies):>{AMPLE - 14}}")

def pausar():
    """Atura l'execucio fins que l'usuari prem Intro."""
    input("\nPrem Intro per tornar al menu...")

# --- Accions del menu ---
def registrar_tasca():
    """Demana les dades d'una tasca i retorna els quatre camps."""
    titol = demanar_text("Titol         : ")
    responsable = demanar_opcio("Responsable   : ", EQUIP).capitalize()
    prioritat = demanar_opcio("Prioritat     : ", PRIORITATS)
    dies = demanar_enter("Dies (1-365)  : ", 1, 365)
    return titol, responsable, prioritat, dies

def canviar_prioritat(titol, prioritat):
    """Demana una prioritat nova i retorna la que queda vigent."""
    nova = demanar_opcio("Nova prioritat: ", PRIORITATS)
    print(f"Prioritat de '{titol}': {prioritat} -> {nova}")
    return nova

def marcar_completada(titol, completada):
    """Retorna l'estat de completada despres de preguntar a l'usuari."""
    if completada:
        print("La tasca ja estava completada.")
        return True
    if confirmar(f"Marcar '{titol}' com a completada?"):
        print("Tasca completada. Bona feina.")
        return True
    print("Operacio cancellada.")
    return False

def main():
    """Executa el bucle principal de l'aplicacio."""
    hi_ha_tasca = False
    titol = ""
    responsable = ""
    prioritat = ""
    dies = 0
    completada = False

    while True:
        mostrar_menu()
        opcio = demanar_opcio("Tria una opcio (1-5): ", OPCIONS)

        if opcio == "5":
            if confirmar("Segur que vols sortir?"):
                print("Fins despres. TascaFacil es tanca.")
                break
        elif opcio == "1":
            if hi_ha_tasca and not confirmar(f"Ja existeix '{titol}'. Substituir-la?"):
                print("Operacio cancellada.")
            else:
                titol, responsable, prioritat, dies = registrar_tasca()
                completada = False
                hi_ha_tasca = True
                print("Tasca registrada correctament.")
        elif not hi_ha_tasca:
            print("Encara no hi ha cap tasca registrada.")
        elif opcio == "2":
            mostrar_fitxa(titol, responsable, prioritat, dies, completada)
        elif opcio == "3":
            prioritat = canviar_prioritat(titol, prioritat)
        elif opcio == "4":
            completada = marcar_completada(titol, completada)

        pausar()

if __name__ == "__main__":
    main()

El que ha canviat, punt per punt:

  • El bucle principal cap en vint línies i es llegeix com una taula de decisions. Ja no hi ha ni un input ni un print de formatatge a dins: només crides a funcions amb nom.
  • if not hi_ha_tasca: estava escrit tres vegades; ara està una. El truc és l'elif not hi_ha_tasca: col·locat després de les opcions 5 i 1 —les dues úniques que funcionen sense tasca registrada— i abans de les opcions 2, 3 i 4. Si no hi ha tasca, la cadena d'elif s'atura allà i cap de les tres no s'executa.
  • Les quatre validacions duplicades són ara tres funcions, i demanar_opcio serveix per al menú, per al responsable i per a la prioritat. confirmar(missatge) unifica a més les tres confirmacions i tanca en un sol lloc la decisió que només "s" confirma.
  • registrar_tasca() retorna quatre valors que es desempaqueten de cop (04-02), i canviar_prioritat i marcar_completada retornen el nou valor en comptes de modificar-lo pel seu compte: cap funció no toca l'estat que no li pertany, com mana 04-03.
v0.6 v0.7
Línies totals ~95 ~150
Línies del bucle principal ~75 22
Funció més llarga 75 (tot el bucle) 10 (mostrar_menu)
Bucles de validació escrits 5 3 (en funcions)
Comprovacions not hi_ha_tasca 3 1
Funcions reutilitzables fora del programa 0 8

Sí: el fitxer té més línies que abans. És el normal en una refactorització i no és mal negoci, perquè el que es mesura no és quant ocupa el programa sinó quant cal llegir per entendre'n un tros: abans, per saber què feia l'opció 3, calia llegir les setanta-cinc línies del bucle; ara se'n llegeixen quatre. Queda, això sí, un cap solt, i és gros. Mira la capçalera de mostrar_fitxa: cinc paràmetres que són sempre els mateixos cinc, viatjant junts de funció en funció. I mira el començament de main(): sis variables soltes declarades una darrere l'altra. Aquestes sis variables són una sola cosa —una tasca— que encara no té manera de ser una sola cosa al nostre codi. Quan coneguis les tuples i estructures imbricades les podràs agrupar, i quan arribis a les classes els podràs donar nom propi i comportament. Fins llavors, viatgen de la mà.

Errors Comuns i Consells

Extreure funcions que continuen depenent de globals. Moure deu línies a un def no és descompondre si aquestes línies continuen llegint i escrivint variables del programa principal. Comprova cada funció amb la prova del retall de 04-03. I les funcions que fan dues coses solen delatar-se en el nom (validar_i_desar) o en descriure-les: parteix-les, encara que cada meitat quedi molt curta.

Barrejar nivells d'abstracció. Un main() amb un print("=" * 46) enmig de crides d'alt nivell: aquest print pertany a mostrar_menu. El defecte contrari és sobrefragmentar: vint funcions de dues línies fetes servir una sola vegada són tan difícils de llegir com un bloc de dues-centes. Refactoritzar i afegir funcionalitat alhora. És la recepta per no saber què ha trencat què. Primer reorganitza deixant el comportament idèntic, comprova que tot continua igual, i només llavors afegeix el nou. I no oblidis l'if __name__ == "__main__":, ni deixis codi solt al marge esquerre entre les definicions: s'executarà tan bon punt algú importi el fitxer.

Consell: refactoritza en passos petits i executa després de cadascun. Extreu una funció, executa, comprova; si alguna cosa falla, saps exactament quin pas ho ha causat. I escriu el main() com t'agradaria que fos: si en llegir-lo entens el programa sense obrir cap altra funció, la descomposició és bona, i de passada tens la millor documentació que tindrà el teu programa.

Exercicis

Exercici 1: Descompondre un guió

Aquest programa funciona però està escrit d'una tirada. Identifica'n les responsabilitats, proposa els noms de les funcions en què el partiries —indicant paràmetres i què retorna cadascuna— i escriu el main() resultant.

nom = input("Client: ").strip()
while nom == "":
    nom = input("No pot estar buit. Client: ").strip()
hores = input("Hores: ").strip()
while not hores.isdigit() or int(hores) < 1:
    hores = input("Enter mes gran que 0. Hores: ").strip()
hores = int(hores)
import_total = hores * 55.0
if hores > 40:
    import_total = import_total * 0.9   # descompte del 10% per volum
print("=" * 40)
print(f"Client: {nom}")
print(f"Import: {import_total:.2f} EUR")

Exercici 2: Diagnosticar una descomposició

Un company ha partit el seu programa en aquestes tres funcions. Assenyala quatre defectes de disseny, cadascun amb el criteri de la lliçó que incompleix, i proposa una alternativa.

def processar():                         # declara 'global total'
    dades = input("Dada: ")              # demana una dada a l'usuari
    total = total + int(dades)           # actualitza la global
    print(f"Total: {total}")             # l'imprimeix
    return total                         # i a mes el retorna

def sumar_dos(a, b):
    return a + b

def validar_i_mostrar_client(nom):       # si esta buit avisa; si no, l'imprimeix
    ...

Solucions

Solució 1. Hi ha quatre responsabilitats: demanar el nom validat, demanar les hores validades, calcular l'import amb el seu descompte i presentar el rebut. La lògica del descompte ha de quedar aïllada de l'entrada i de la sortida.

TARIFA = 55.0
AMPLE = 40

def demanar_text(missatge):
    """Demana un text obligatori i el retorna net."""
    valor = input(missatge).strip()
    while valor == "":
        valor = input("No pot estar buit. " + missatge).strip()
    return valor

def demanar_enter_positiu(missatge):
    """Demana un enter mes gran que zero i el retorna convertit."""
    text = input(missatge).strip()
    while not text.isdigit() or int(text) < 1:
        text = input("Enter mes gran que 0. " + missatge).strip()
    return int(text)

def calcular_import(hores, tarifa=TARIFA):
    """Retorna l'import, amb un 10% de descompte per sobre de 40 hores."""
    brut = hores * tarifa
    if hores > 40:
        return brut * 0.9
    return brut

def mostrar_rebut(nom, quantia):
    """Pinta el rebut emmarcat del client."""
    print("=" * AMPLE)
    print(f"Client: {nom}")
    print(f"Import: {quantia:.2f} EUR")

def main():
    """Demana les dades de l'encarrec i mostra el rebut."""
    nom = demanar_text("Client: ")
    hores = demanar_enter_positiu("Hores: ")
    mostrar_rebut(nom, calcular_import(hores))

if __name__ == "__main__":
    main()

Fixa't que calcular_import no imprimeix ni pregunta: pots comprovar a mà que calcular_import(40) dona 2200.0 i calcular_import(41) dona 2029.5, sense executar el programa. I que el main() té tres línies que es llegeixen com l'enunciat del problema.

Solució 2.

Defecte Criteri incomplert Alternativa
processar fa servir global total Una funció no ha de dependre d'estat global canviant (04-03) def acumular(total, dada): return total + dada
processar demana, calcula, imprimeix i retorna Una funció, una responsabilitat Separar en demanar_enter, acumular i mostrar_total
sumar_dos és sobrefragmentació No es reutilitza, no aclareix res, no amaga complexitat Escriure a + b on calgui
validar_i_mostrar_client porta «i» al nom Dues responsabilitats: validar i presentar def es_nom_valid(nom): return nom != "" més mostrar_client(nom)

A més, el nom processar és genèric i no adverteix que modifica l'estat global. Un nom honest per al que fa seria demanar_dada_i_acumular_la_al_total: la seva mateixa lletjor demostra que la funció està mal partida.

Conclusió

Descompondre un programa no és tallar-lo a trossos: és trobar-ne les parts. Els criteris són pocs i comprovables: una funció, una responsabilitat, verificable amb la prova de descriure-la sense fer servir «i»; una mida que rarament passa de vint línies; un nivell d'abstracció homogeni dins de cada funció; entrada, lògica i sortida en famílies separades, perquè la lògica silenciosa és l'única que es pot comprovar de debò; noms que anuncien l'efecte; DRY per no repetir-se, i sentit comú per no fragmentar de més. El disseny descendent —escriure el main() com si les funcions ja existissin— és la manera més còmoda d'aplicar tot això, i el bloc if __name__ == "__main__": tanca el fitxer perquè es pugui executar o importar.

TascaFàcil ha arribat a la versió 0.7. Fa exactament el mateix que la v0.6 —ni una funció nova de cara a la Marta—, però el seu bucle principal ha passat de setanta-cinc línies a vint-i-dues, la duplicació ha desaparegut i vuit de les seves funcions es poden reutilitzar tal qual en un altre programa. L'estat de la tasca, això sí, continua vivint en sis variables soltes que cal passar de funció en funció: és el deute que el mòdul 5 i el 7 vindran a cobrar. Queda una última sorpresa abans de tancar el mòdul. Fins ara les funcions han estat coses que es criden; però a 04-01 vas veure de passada que pausar sense parèntesis és un valor amb el seu propi type(). Si una funció és un valor, es pot desar en una variable, passar com a argument a una altra funció i retornar des d'una altra. Això obre una manera de programar diferent, i és el tancament del mòdul: Funcions com a valors: lambda i ordre superior.

© Copyright 2026. Tots els drets reservats