A la lliçó anterior vas fer servir noms com preu o estoc per desar valors. Aquests noms són variables, i en aquesta lliçó les estudiem a fons: què passa exactament en assignar, quins noms són vàlids i quins recomana la guia d'estil PEP 8, com assignar diversos valors de cop, com s'expressen les constants en Python i una primera aproximació a dues idees que t'acompanyaran tot el curs: l'àmbit de les variables i la diferència entre reassignar i mutar. Anomenar i organitzar bé les dades és la meitat de la feina de programar; el sistema de Papyrus començarà a semblar-se a un programa de debò.
Contingut
- Què és una variable i com funciona l'assignació
- Regles de noms (el que Python exigeix)
- Convencions de noms: PEP 8 i snake_case
- Assignació múltiple i intercanvi de valors
- Constants per convenció
- Àmbit bàsic a nivell de script
- Mutabilitat vs reassignació (introducció conceptual)
Què és una variable i com funciona l'assignació
Una variable és un nom associat a un valor. Es crea amb l'operador d'assignació =:
La manera correcta de llegir botiga = "Papyrus" és: "el nom botiga passa a referir-se al valor "Papyrus"". L'ordre importa: a l'esquerra el nom, a la dreta el valor. A l'inrevés ("Papyrus" = botiga) és un error de sintaxi.
Un matís que en Python és més literal que en altres llenguatges: la variable no és una caixa que conté el valor, sinó una etiqueta que apunta al valor. El valor existeix en memòria, i el nom és una referència cap a ell:
flowchart LR
A["botiga"] --> V1["'Papyrus' (str)"]
B["preu_odissea"] --> V2["12.50 (float)"]
C["estoc_odissea"] --> V3["4 (int)"]
Aquesta imatge d'"etiquetes sobre valors" et serà molt útil a l'apartat final de la lliçó i, més endavant, amb les llistes del mòdul 4.
Un cop creada, la variable es fa servir escrivint-ne el nom:
I pot reassignar-se: apuntar a un valor nou, oblidant l'anterior:
És molt comú reassignar una variable fent servir el seu propi valor actual:
Aquí no hi ha cap paradoxa matemàtica: primer s'avalua la dreta (3 - 1 → 2) i després el nom passa a apuntar al resultat. Python ofereix dreceres per a aquestes operacions, els operadors d'assignació augmentada:
| Drecera | Equival a | Ús típic a Papyrus |
|---|---|---|
x += n |
x = x + n |
arribar una comanda: estoc += 10 |
x -= n |
x = x - n |
vendre: estoc -= 1 |
x *= n |
x = x * n |
duplicar un preu |
x /= n |
x = x / n |
aplicar meitat de preu |
Recorda de la lliçó anterior: no confonguis = (assignar) amb == (comparar).
Finalment, fer servir una variable que encara no existeix produeix un error:
Les variables s'han d'assignar abans de fer-les servir: els scripts s'executen de dalt a baix.
Regles de noms (el que Python exigeix)
Python imposa unes poques regles dures sobre els noms de variables. Si les incompleixes, el programa ni tan sols arrenca (SyntaxError):
- Només lletres, dígits i guions baixos (
_). Res d'espais, guions-ni símbols. - No poden començar per un dígit:
2llibresés invàlid;llibres2és vàlid. - No poden ser paraules reservades del llenguatge:
if,for,while,and,or,not,True,False,None,class,def,import,return... (n'hi ha 35; el REPL te les llista ambhelp("keywords")). - Majúscules i minúscules es distingeixen:
preu,PreuiPREUsón tres variables diferents.
| Nom | Vàlid? | Motiu |
|---|---|---|
estoc_odissea |
Sí | Lletres i guió baix |
llibre2 |
Sí | El dígit no va al principi |
2llibre |
No | Comença per dígit |
estoc-odissea |
No | El guió - és l'operador resta |
preu llibre |
No | No es permeten espais |
class |
No | Paraula reservada |
títol |
Sí (legal) | Python 3 admet accents i ç, però evita-ho (apartat següent) |
Convencions de noms: PEP 8 i snake_case
A més de les regles obligatòries, existeix la guia d'estil oficial de Python, PEP 8 (Python Enhancement Proposal 8), que recomana com hauries d'escriure el codi perquè sigui llegible i homogeni. Les seves convencions de noms més rellevants ara:
- Variables i funcions:
snake_case— tot en minúscules, paraules separades per guions baixos:preu_odissea,total_venda,nom_client. - Constants:
MAJUSCULES_AMB_GUIONS:IVA_LLIBRES,NOM_BOTIGA(les veiem de seguida). - Classes:
PascalCase(cada paraula amb inicial majúscula):Llibre,ClientHabitual— ho faràs servir al mòdul 5. - Evita noms amb accents o
çencara que siguin legals, i evitalsola,Omajúscula sola oImajúscula sola (es confonen amb1i0).
| Estil | Exemple | Es fa servir per a |
|---|---|---|
snake_case |
preu_amb_iva |
variables i funcions |
MAJUSCULES |
IVA_LLIBRES |
constants |
PascalCase |
LlibreDeSegonaMa |
classes (mòdul 5) |
camelCase |
preuAmbIva |
no es fa servir en Python (és de Java/JavaScript) |
Tan important com el format és l'expressivitat. Compara:
# Malament: que es cada cosa?
x = 12.50
y = 3
z = x * y
# Be: el codi s'explica sol
preu_unitari = 12.50
unitats_venudes = 3
total_venda = preu_unitari * unitats_venudesTots dos fragments fan el mateix, però el segon el pot llegir (i mantenir) qualsevol sense endevinar res. Regla pràctica: el nom ha de dir què conté la variable, no com es calcula ni de quin tipus és.
Assignació múltiple i intercanvi de valors
Python permet assignar diverses variables en una sola línia, separant amb comes tots dos costats:
És equivalent a tres assignacions, però més compacte quan els valors estan relacionats (aquí, les tres dades d'una fitxa de llibre). Hi ha d'haver el mateix nombre de noms que de valors, o Python llança ValueError.
També es pot assignar el mateix valor a diversos noms:
I la joia de la corona: l'intercanvi de valors (swap) sense variable auxiliar. En molts llenguatges intercanviar dues variables requereix una tercera de temporal; en Python:
prestatge_a = "L'Odissea"
prestatge_b = "Hamlet"
# L'Anna reordena l'aparador: els llibres canvien de prestatge
prestatge_a, prestatge_b = prestatge_b, prestatge_a
print(prestatge_a) # Hamlet
print(prestatge_b) # L'OdisseaFunciona perquè Python avalua primer tot el costat dret (amb els valors antics) i després assigna a l'esquerre. Aquest mecanisme, anomenat desempaquetatge, donarà molt més joc amb les tuples del mòdul 4.
Constants per convenció
Una constant és un valor que no hauria de canviar durant l'execució del programa: un tipus d'IVA, el nom de la botiga, un descompte fix.
Aquí Python és peculiar: no té constants reals. No existeix cap paraula clau que impedeixi reassignar una variable. En el seu lloc, la comunitat fa servir una convenció: els noms en MAJUSCULES_AMB_GUIONS signifiquen "això és una constant, no la toquis".
# Constants del sistema de Papyrus (van al principi de l'script)
NOM_BOTIGA = "Papyrus"
IVA_LLIBRES = 0.04 # 4% (fictici, per als exemples)
DESCOMPTE_SOCI = 0.05 # 5% per a clients socis
# Us normal
preu_base = 12.50
preu_final = preu_base * (1 + IVA_LLIBRES)
print(f"{NOM_BOTIGA}: preu final {preu_final:.2f} euros")Punts clau:
- Python no impedirà que escriguis
IVA_LLIBRES = 0.21més avall; simplement cap programador respectable no ho fa. És un contracte entre humans. - Les constants es declaren al principi de l'script, agrupades, perquè qui llegeixi el codi trobi en un sol lloc els valors de configuració.
- Avantatge enorme: si l'IVA canvia, el modifiques en una línia, en lloc de buscar
0.04escampat per tot el programa. Els valors numèrics solts i repetits pel codi s'anomenen despectivament nombres màgics; les constants en són l'antídot.
Àmbit bàsic a nivell de script
L'àmbit (scope) d'una variable és la zona del programa on aquell nom existeix i es pot fer servir. Com que encara no escrivim funcions (arriben al mòdul 3), els teus scripts treballen en un únic àmbit, anomenat àmbit global del mòdul, i les regles són senzilles:
- Una variable existeix des de la línia en què s'assigna fins al final de l'script.
- Fer-la servir abans d'aquesta línia produeix
NameError. - Al REPL passa el mateix: les variables viuen des que les defineixes fins que tanques la sessió.
# fitxa.py
print(NOM_BOTIGA) # NameError: encara no existeix
NOM_BOTIGA = "Papyrus"
print(NOM_BOTIGA) # ara si: PapyrusDues conseqüències pràctiques:
- Ordre lògic: defineix primer (constants i dades a dalt), fes servir després. Un script ben organitzat es llegeix de dalt a baix com una recepta.
- Compte a reutilitzar noms: si anomenes
preutres coses diferents al llarg de l'script, la variable anirà canviant de valor i el codi serà confús. Millor noms específics:preu_odissea,preu_hamlet.
Quan arribin les funcions veuràs que creen el seu propi àmbit local (variables que només existeixen dins de la funció); de moment, queda't amb la idea que on defineixes una variable determina on pots fer-la servir.
Mutabilitat vs reassignació (introducció conceptual)
Acabem amb una distinció conceptual que evitarà moltes confusions futures. Hi ha dues maneres que "alguna cosa canviï" en un programa:
| Concepte | Què canvia | Exemple |
|---|---|---|
| Reassignació | L'etiqueta passa a apuntar a un altre valor. El valor antic no es modifica. | estoc = 5 i després estoc = 4 |
| Mutació | El valor mateix es modifica per dins, sense canviar d'etiqueta. | Afegir un llibre a una llista (mòdul 4) |
Tots els tipus que coneixes fins ara — int, float, str, bool, None — són immutables: els seus valors no es poden modificar per dins. Quan fas estoc = estoc - 1, no estàs "rebaixant" el nombre 5; estàs creant/obtenint el nombre 4 i movent l'etiqueta cap a ell. El 5 continua sent 5, intocable.
Amb les cadenes de text es veu molt clar:
titol = "l'odissea"
titol.upper() # produeix "L'ODISSEA"... pero no canvia titol
print(titol) # l'odissea (segueix igual!)
titol = titol.upper() # per "canviar-la" cal REASSIGNAR
print(titol) # L'ODISSEALes operacions sobre tipus immutables retornen valors nous; si vols conservar el resultat, reassigna.
I la mutació? Apareixerà al mòdul 4 amb les llistes: una llista sí que es pot modificar per dins (afegir, treure, reordenar elements) sense reassignar la variable. Llavors la imatge d'"etiquetes que apunten a valors" serà crucial, perquè dues etiquetes poden apuntar a la mateixa llista i els canvis es veuran des de totes dues. Per ara n'hi ha prou amb la idea:
- Reassignar = moure l'etiqueta a un altre valor (possible sempre).
- Mutar = canviar el valor per dins (només amb tipus mutables, que encara no hem vist).
Errors Comuns i Consells
NameError: name '...' is not defined: fas servir la variable abans d'assignar-la, o l'has escrita amb una errada (recorda quePreuipreusón diferents).- Noms críptics:
p,x2,dada. D'aquí a dues setmanes ni tu sabràs què eren. Inverteix cinc segons en un bon nom; els recuperaràs multiplicats. - camelCase en Python:
preuFinalfunciona, però desentona amb tot l'ecosistema. En Python,snake_case:preu_final. - Trepitjar una constant: escriure
IVA_LLIBRES = 0.21a mig script és legal però trenca el contracte de les majúscules. Si un valor canvia durant l'execució, és que no era una constant: anomena'l en minúscules. - Fer ombra a noms de Python: evita anomenar les teves variables
print,str,type... És legal, però "tapa" la funció original (print = 5faria queprint("hola")fallés la resta de l'script). - Esperar que
titol.upper()canviïtitol: les cadenes de text són immutables; el resultat s'ha de reassignar. - Consell: quan dubtis si un nom és bo, llegeix-lo dins d'una frase: "el
preu_unitariper lesunitats_venudesdona eltotal_venda". Si la frase sona natural, els noms són bons.
Exercicis
Exercici 1
Indica si cada nom és invàlid (Python dona error), legal però contrari a PEP 8, o correcte per a una variable normal:
total-vendaTotalVendatotal_venda2n_llibre_descomptefor
Exercici 2
Escriu un script per a Papyrus que:
- Defineixi les constants
NOM_BOTIGA = "Papyrus"iDESCOMPTE_SOCI = 0.05. - Creï amb assignació múltiple en una sola línia les variables
titol,preuiestocamb els valors"El Quixot",15.90i8. - Simuli la venda de 2 exemplars a en Lluís (que és soci): actualitzi
estocamb un operador d'assignació augmentada i calculi el total amb el descompte aplicat. - Mostri amb f-strings l'estoc restant i el total cobrat amb dos decimals.
Exercici 3
L'Anna ha etiquetat malament dos llibres i cal intercanviar-ne els preus. Partint d'aquestes variables, intercanvia'ls sense fer servir cap variable auxiliar i mostra el resultat:
preu_odissea = 9.95 # hauria de ser el de Hamlet
preu_hamlet = 12.50 # hauria de ser el de L'OdisseaDesprés, respon: després d'executar preu_odissea = 12.50, s'ha mutat el valor 9.95? Per què?
Solucions
Solució 1
total-venda— invàlid: el guió és l'operador resta; Python el llegeix comtotal - venda.TotalVenda— legal però contrari a PEP 8: és PascalCase, reservat per convenció per a les classes.total_venda— correcte: snake_case perfecte.2n_llibre— invàlid: no pot començar per dígit._descompte— legal: el guió baix inicial és vàlid (per convenció suggereix "ús intern", ho veuràs al mòdul 5); per a una variable normal n'hi hauria prou ambdescompte.for— invàlid: paraula reservada.
Solució 2
# venda_soci.py
NOM_BOTIGA = "Papyrus"
DESCOMPTE_SOCI = 0.05
titol, preu, estoc = "El Quixot", 15.90, 8
# Venda de 2 exemplars a en Lluis (soci)
unitats = 2
estoc -= unitats
total = preu * unitats * (1 - DESCOMPTE_SOCI)
print(f"{NOM_BOTIGA}: venuts {unitats} x {titol}")
print(f"Estoc restant: {estoc}")
print(f"Total cobrat: {total:.2f} euros")estoc -= unitats equival a estoc = estoc - unitats; i (1 - DESCOMPTE_SOCI) és 0.95, és a dir, pagar el 95% de l'import.
Solució 3
preu_odissea = 9.95
preu_hamlet = 12.50
preu_odissea, preu_hamlet = preu_hamlet, preu_odissea
print(f"L'Odissea: {preu_odissea:.2f} euros") # 12.50
print(f"Hamlet: {preu_hamlet:.2f} euros") # 9.95Python avalua primer el costat dret sencer (12.50, 9.95, amb els valors antics) i després l'assigna a l'esquerre, aconseguint l'intercanvi en una línia.
Resposta a la pregunta: no hi ha mutació. Els float són immutables: 9.95 continua existint tal qual; l'únic que ha passat és que l'etiqueta preu_odissea ara apunta a un altre valor (12.50). És una reassignació.
Conclusió
Ara domines la peça central de qualsevol programa: les variables com a etiquetes que apunten a valors, l'assignació (simple, augmentada i múltiple), les regles de noms i les convencions PEP 8 (snake_case per a variables, MAJÚSCULES per a constants), l'àmbit bàsic d'un script que es llegeix de dalt a baix, i la diferència conceptual entre reassignar una etiqueta i mutar un valor. Papyrus ja té constants de configuració i la seva primera venda amb descompte a en Lluís.
Fins ara, totes les dades estaven escrites dins del codi. A la propera lliçó, Entrada i Sortida Bàsica, el programa prendrà vida: aprendràs a demanar dades a l'usuari amb input(), a donar format professional a la sortida i construiràs el primer programa interactiu de Papyrus.
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
