Comentaris, estil i primeres bones pràctiques
El codi no s’escriu només per a què funcioni. També s’escriu per a què algú més (inclòs tu dins de tres setmanes) ho entengui. A Python, com a qualsevol llenguatge, la llegibilitat no és opcional. I tot i que black, flake8 o pylint poden ajudar-te a corregir l’estil, l’essencial és saber quines certes decisions fan el codi més clar o més difícil de mantenir.
En aquesta entrada ens centrem a:
- Com escriure comentaris útils (i què evitar)
- Triar noms de variables que no molestin
- Organitzar el codi perquè no sembli un bolcat mental
- Estil general i convencions que sí que importen
- Primeres pràctiques d’ escriptura neta que convé adquirir des del principi
1. Comentaris: quan escriure’ls, com escriure’ls i què evitar
Els comentaris a Python (i en qualsevol llenguatge) tenen una funció senzilla: explicar el que el codi no diu per si mateix. El problema és que molta gent els fa servir malament. Alguns comenten tot, fins i tot l’obvi. D’altres no escriuen ni un de sol, confiant que “ja s’entén”. Ambdós extrems causen problemes.
Els comentaris no són per omplir, ni per impressionar. Són per ajudar. Ajudar la persona que vindrà després —i gairebé sempre, aquesta persona ets tu. Un bon comentari dona context, no repeteix el codi. És com un cartell ben posat: breu, clar, al lloc just.
Saber comentar bé no és escriure més, és escriure només quan cal i dir el que de veritat importa.
1.1 Tipus de comentaris
Hi ha tres formes de comentar a Python:
- Comentari en línia: comença amb #, en la seva pròpia línia o al final d’ una línia de codi.
- Docstring: una cadena entre triples cometes al principi d’ una funció, classe o mòdul.
- Comentaris temporals: línies de codi comentades, normalment per a proves. No haurien de quedar en el codi final.
Vegem-los un a un.
1.2 Comentaris en línia
El típic # per a explicar alguna cosa. Útils quan aporten context. Poden anar abans o al costat del codi.
# Convertim la temperatura de Fahrenheit a Celsius
temp_c = (temp_f - 32) * 5 / 9
resultat = calcular_preu_final() # inclou impostos i descomptes
Quan fer-los servir:
- Per a explicar per què fas alguna cosa (no què fas).
- Per aclarir un ús no evident o evitar confusió.
- Per assenyalar una limitació o comportament inusual.
Quan evitar-los:
- Per a repetir el que ja diu el codi.
- Per a “narrar” línia per línia.
Exemple real:
# Evitem fer servir get() perquè necessitem llençar excepció si falta
user_id = data["user_id"]
Aquí el comentari justifica una decisió poc evident, que podria semblar un oblit.
1.3 Docstrings: documentació estructurada
Les docstrings són cadenes multilínia que serveixen com a documentació oficial per a funcions, classes i mòduls. A diferència dels comentaris normals, s’hi poden accedir des del codi (help(), .__doc__, generació automàtica de docs, etc).
Exemple de funció amb docstring:
def calcular_preu_total(productes, incloure_enviament =False):
"""
Calcula el preu total d' una llista de productes.
Args:
productes (list): Llista de diccionaris amb claus 'preu' i 'quantitat'.
incloure_enviament (bool): Si es suma el cost de l'enviament al total.
Returns:
float: Preu total calculat.
"""
...
Fer servir docstrings des del començament té diversos avantatges:
- Ajuda a dissenyar bé una funció (t’obliga a pensar en entrades i sortides).
- Permet generar documentació automàtica.
- Millora la comprensió sense necessitat d’ obrir el codi.
Hi ha diversos estils (Google, NumPy, reStructuredText). L’important és ser consistent dins d’un projecte.
1.4 Comentaris temporals i codi comentat
# usuaris = carregar_usuaris_des_de_bd()
usuaris = MOCK_USERS # fer servir dades fixes durant proves
És vàlid durant el desenvolupament, però deixa rastre si no ho neteges. Codi comentat que es “queda per si de cas” es torna brossa tècnica en poc temps.
Regla clara: si està comentat i porta setmanes aquí, esborra’l o fes-ho configurable.
1.5 Què comentar (i què no)
Aquí van decisions pràctiques:
Situació | Comentari? | Què posar |
Fórmules complexes o no òbvies | Sí | Què representa i per què es calcula així |
Recerques o accessos a estructures de dades complicades | Sí | Què estem buscant i per què |
Workarounds, hacks o compatibilitat amb versions | Sí | Quina és la limitació i per què es fa així |
Comportament inesperat d’una llibreria externa | Sí | Referència al bug o documentació |
Trucades a funcions ben nomenades i autoexplicatives | No | El codi ja ho diu tot |
Estructures simples i trivials | No | Evita comentar l’obvi |
Codi temporal o desactivat | De vegades | Posen un TODO amb data o issue, o esborra’l |
1.6 Comentaris com a marques de tasques
Hi ha convencions per assenyalar coses que estan pendents, trencades o per revisar:
# TODO: reemplaçar aquest mètode quan es migri a la nova API
# FIXME: això falla quan el camp 'data' és None
Aquestes marques poden integrar-se amb editors, linters i sistemes de CI. Però si no les has de rastrejar, no les posis.
Consell: acompanya-les amb data o autor si han de quedar un temps.
# TODO (miguel, 2025-07-10): eliminar quan s'utilitzi la nova API de factures
1.7 Comentaris vs bon codi
Sovint, el millor comentari és un nom ben posat.
Exemple:
# Comprovem si l'usuari és major d'edat
if edat >= 18:
...
És millor això:
es_major_d_edat = edat > = 18
if es_major_d_edat:
...
Noms clars reemplacen molts comentaris innecessaris.
Un altre exemple més clar:
# Calcular ràtio entre aprovats i total
ràtio = aprovats / total_alumnes
Millor així:
percentatge_aprovats = aprovats / total_alumnes
Si el nom expressa la intenció, el comentari sobra.
1.8 Comentaris multilínia (blocs de context)
Quan un bloc de codi depèn d’ una decisió tècnica o negoci complexa, un comentari explicatiu previ pot estalviar molt de temps al següent que llegeixi el codi.
# Si el pagament és per transferència, no podem confirmar automàticament.
# Necessitem que ho validi manualment.
if metode_pagament = = "transferència":
estat = "pendent_revisió"
else:
estat = "confirmat"
Aquest tipus de comentari sí que aporta valor: respon al “per què es fa així?”, no només al “què fa?”.
1.9 Comentaris que envelleixen malament
Un problema habitual: comentaris que eren correctes fa mesos, però el codi va canviar i ningú els va actualitzar.
# Fem servir GET perquè l'API no permet POST en aquest endpoint
response = requests.post(url, data=data)
Aquest comentari no només és inútil: és fals. Enganya.
Consell pràctic: si no has de mantenir-lo, no ho posis. De vegades és millor obligar-se a llegir el codi que confiar en comentaris obsolets.
1.10 Revisió de comentaris en code review
Quan fas revisió de codi (propi o aliè), passa sempre per aquests punts:
- El comentari explica una cosa que el codi no deixa clar?
- Està actualitzat i és coherent amb el codi real?
- Podria el comentari eliminar-se si el codi es reescriu millor?
- Es refereix a comportament real o a intencions passades?
És habitual trobar comentaris tipus:
# Això es va arreglar amb el pegat temporal de juliol
...
Que ja no tenen sentit sis mesos després. Si és història, treu-lo del codi i del changelog, documentació o l’ historial de git.
1.11 Comentaris com a forma de pensar
Un truc útil: quan no tens clar com resoldre alguna cosa, escriu primer el comentari del que vols que passi. Després tradueix-lo a codi.
# Si l'usuari no té comandes, mostrar missatge de benvinguda
if not usuari.comandes:
mostrar_benvinguda()
Aquesta tècnica pot ajudar-te a escriure codi més expressiu, perquè primer t’obliga a pensar en termes humans.
1.12 Comentaris en altres idiomes
Regla general: escriu els comentaris en l’ idioma que es fa servir en la resta del projecte.
Si és un projecte en anglès, comenta en anglès. Si és personal o local, català està bé. L’important és no barrejar ni escriure comentaris per a un de sol.
2. Noms de variables: clars, sense obsessionar-se
No hi ha res més molest que llegir codi amb variables com a, b, tmp, data1, foo. També és un error l’ extrem contrari: noms larguíssims que repeteixen el context ja donat pel propi nom de la funció o classe.
Exemples de noms dolents
def get_data(d):
for x in d:
do_something(x)
Aquí no sabem què és d, ni què és x. Això costa segons extra cada vegada que es llegeix, i s’acumula.
Millors noms
def get_data(entries):
for entry in entries:
do_something(entry)
Podem fer-ho encara millor? Depèn de què representa cada cosa:
def get_usernames(users):
for user in users:
yield user["username"]
Aquí queda clar què esperem d’users i què retorna la funció.
Bones pràctiques
- Fes servir noms descriptius, però sense guarniments ni repeticions innecessàries.
- Si el context ja és evident, no el repeteixis:
# Dolent
def get_user_name_from_user(user):
return user.name
# Millor
def get_user_name(user):
return user.name
- Per a bucles simples on el context ho permet, Fer servir i, j o item és acceptable, però no fora de blocs petits.
for i in range(10): # bé si és un bucle curt
...
Si i representa una altra cosa, fes servir un nom més específic.
- Evita noms tipus data, info, stuff, thing llevat que estiguis fent una cosa realment genèrica.
3. Organització bàsica del codi
Ordre lògic dins d’ un arxiu
Quan algú obre el teu arxiu, hauria de poder veure en segons:
- Què fa l’ script o mòdul
- On comença la lògica principal
- Quines parts són auxiliars
Un ordre típic (en mòduls simples) podria ser:
# imports
import os
import sys
# constants
DEFAULT_TIMEOUT = 5
# funcions auxiliars
def cargar_configuracion():
...
def validar_usuario( usuari):
...
# lògica principal
def main():
...
if __name__ == "__main__":
main()
Això ajuda molt a qui arriba de nou a l’arxiu. Si tot està barrejat, cada lectura requereix escanejar tot l’arxiu buscant on comença “l’important”.
Espais i separació
Python és molt sensible als espais (literalment), però també ho és a nivell visual. Fer servir espais en blanc amb intenció millora molt la llegibilitat.
Exemple:
# separa funcions entre si amb una línia
def foo():
pass
def bar():
pass
Dins d’ una funció, fa servir línies en blanc per marcar blocs lògics diferents:
def processar_dades(entrada):
dades_filtrades = [d for d in entrada if d > 0]
resultats = []
for dada in dades_filtrades:
resultats.append(analitzar(dada))
return resultats
Això ajuda a “llegir” l’estructura encara que no hi hagi comentaris.
4. Convencions d’estil (PEP 8)
Python té una guia d’estil oficial: PEP 8. No cal conèixer-la de memòria, però seguir les seves normes bàsiques fa que el teu codi sigui més fàcil de llegir per a qualsevol que hagi treballat amb Python.
Alguns punts essencials:
4.1. Noms
- Funcions i variables: snake_case
- Classes: CamelCase
- Constants: MAJÚSCULES_AMB_GUIONS
def calcular_preu_final():
...
class Comanda:
...
TASA_IVA = 0.21
4.2. Longitud de línia
Evita línies que passin els 79 caràcters. Sí, és antic. Sí, les pantalles són més amples. Però a molts editors, o en fer git diff, les línies llargues es tallen. Escriure pensant en això estalvia molèsties.
4.3. Espais
# Correcte
x = 1
y = x + 2
# Incorrecte
x=1
y = x+2
També:
# Correcte
def sumar(a, b):
return a + b
# Incorrecte
def sumar(a,b):
return a+b
No és per estètica, és perquè en estar tot enganxat costa més llegir-lo.
4.4. Imports
Organitzeu-los així:
- Mòduls estàndard
- Mòduls de tercers
- Mòduls locals
Amb una línia en blanc entre cada grup:
import os
import sys
import requests
import numpy as np
from .utils import netejar_text
5. Bons hàbits des del començament
Algunes pràctiques que convé adquirir aviat, encara que no siguin obligatòries:
5.1. No repeteixis codi
Si fas alguna cosa més d’una vegada, probablement sigui una funció. Evita copiar i enganxar fragments. El codi duplicat sovint deriva en errors quan es modifica una part però no una altra.
5.2. Fes servir constants en comptes de valors màgics
# Dolent
if status == 3:
...
# Millor
ESTAT_ACTIU = 3
if status == ESTAT_ACTIU:
...
Fins i tot en scripts petits, això millora la llegibilitat i prevé errors absurds.
5.3. Evita comentaris tipus “TODO: millorar això” si no penses fer-ho
Els TODO, FIXME i similars només tenen sentit si realment estàs fent servir una eina per a rastrejar-los o has de tornar a aquest codi. Si no, són soroll.
5.4. Escriu pensant a llegir, no a presumir
Evita fer servir trucs del llenguatge només perquè són possibles. Per exemple:
# Massa compacte
return [func(x) for x in items if cond(x)]
# Més clar si és complex
resultats = []
for item in items:
if cond(item):
resultats.append(func(item))
return resultats
6. Errors comuns
Molts errors d’estil o males pràctiques no venen de la ignorància, sinó de la pressa. El problema és que pagaràs aquest estalvi de temps diverses vegades després, en bugs, confusió o necessitat de reescriptura. Aquí algunes trampes habituals que convé evitar fins i tot en scripts “de prova”.
6.1. Variables genèriques “per ara”
Estàs escrivint una cosa ràpida i fas servir variables com tmp, result, foo, x. Ho has de canviar després, és clar. Però després et distreus, passa el commit, i aquest nom queda per sempre.
tmp = procesar_archivo(archivo)
if tmp:
for x in tmp:
if x['id'] == id_actual:
fer_alguna_cosa(x)
Aquest fragment es torna il·legible molt ràpid. El problema no és tècnic, sinó humà: quan alguna cosa sembla funcionar, costa justificar l’esforç de refactoritzar-lo. Però si el codi no es pot llegir sense pausa, ja és un problema.
6.2. Comprimir tot en una línia “perquè sí”
Python ho permet, però no ajuda.
if user and user.is_active and user.last_login and (now - user.last_login).days < 30:
send_email(user.email)
¿Funciona? Sí. És còmode de llegir o depurar? No.
Millor així:
if not user:
return
if not user.is_active:
return
if not user.last_login:
return
dies_inactiu = (now - user.last_login).days
if dies_inactiu >= 30:
return
send_email(user.email)
És més llarg, però molt més fàcil d’entendre i mantenir. Aquesta és la diferència entre escriure codi per a màquines o per a humans.
6.3. Comentaris que ja no corresponen al codi
Això passa més sovint del que sembla:
# Aquí filtrem els productes per preu i categoria
productes = filtrar_productes(stock, nomes_disponibles=True)
Aquest comentari ja no reflecteix el que fa la funció. Potser en el passat tenia un filtre més complex, però ara només en queda un. O ha canviat el comportament i no el comentari. És pitjor que no tenir comentari.
Fes neteja periòdica dels comentaris igual que del codi.
6.4. Excés de comentaris perquè el codi és críptic
De vegades veus això:
# Recorre la llista d'usuaris
# Verifica si l'usuari està actiu
# Si està actiu, afegeix el seu email a la llista
for u in usuaris:
if u.activo:
llista_emails.append(u.email)
Això no és un comentari útil, és una traducció paraula per paraula. El comentari només caldria si hi hagués alguna cosa no evident:
# Incloem només usuaris actius perquè els inactius ja no reben notificacions
for u in usuaris:
if u.activo:
llista_emails.append(u.email)
7. Un petit exemple complet amb bones pràctiques
import os
from datetime import datetime
MAX_ANTIGUITAT_DIES = 30
def obtenir_usuaris_actius(usuaris):
"""Retorna una llista amb els emails d’ usuaris actius recents."""
resultat = []
ara = datetime.now()
for usuari in usuaris:
if not usuari.get("actiu"):
continue
data_ultim_login = usuari.get("ultim_login")
if not data_ultim_login:
continue
dies_inactiu = (ara - data_ultim_login).days
if dies_inactiu > MAX_ANTIGUITAT_DIES:
continue
resultat.append(usuari["email"])
return resultat
def enviar_emails(emails):
for email in emails:
print(f"Enviant correu a: {email}") # en real: fer servir llibrería de correu
def main():
# Això normalment vindria d’ una base de dades o API
usuaris = [
{"email": "ana@example.com", "actiu": True, "darrer_login": datetime(2025, 7, 1)},
{"email": "luis@example.com", "actiu": False, " darrer_login ": datetime(2025, 6, 10)},
{"email": "mar@example.com", "actiu": True, " darrer_login ": datetime(2025, 5, 15)},
]
emails = obtenir_usuaris_actius(usuaris)
enviar_emails(emails)
if __name__ == "__main__":
main()
Aquest script no fa res complex, però mostra diverses coses ben organitzades:
- Importacions clares i ordenades.
- Constant amb nom explícit.
- Funció amb nom descriptiu, comentari curt i precís.
- Variables que s’ entenen en llegir.
- Separació entre lògica de negoci (obtenir_usuaris_actius) i de presentació (enviar_emails).
- Punt d’entrada (main) net i reconeixible.
8. Eines que ajuden (però no reemplacen el criteri)
8.1. black
Formatejador automàtic. Si el fas servir, respecta PEP8 gairebé al peu de la lletra. Estalvia discussions d’ estil i fa que el codi llueixi uniforme.
black archivo.py
Pots integrar-lo en editors com VSCode o en pre-commits.
8.2. Floc8 / Ruff
Lanter que detecta errors d’ estil i certes males pràctiques. ruff és més ràpid i modern. No està malament executar-lo abans de fer commit.
ruff archivo.py
8.3. pylint
Més estricte i detallat. De vegades excessiu, però configurable.
9. Criteris per decidir entre opcions vàlides
De vegades hi ha més d’una forma correcta d’escriure alguna cosa. Com triar?
- És llegible sense comentaris? Si necessites explicar massa, reescriu.
- És consistent amb la resta del projecte? Si tot està en snake_case, no introdueixis camelCase.
- ¿Facilita el test? Codi més modular, amb funcions petites, es prova millor.
- S’entén amb poc context? Si has de revisar 5 funcions abans de saber què fa una línia, alguna cosa està malament.
Tancament
Escriure bon codi no es tracta només de fer servir bé Python. Es tracta d’escriure una cosa que tu i d’altres podeu llegir, entendre i modificar sense por. Les eines ajuden, però no substitueixen el criteri. És millor escriure una mica més lent, amb intenció, que ràpid i enredat.
Aquestes primeres pràctiques són la base sobre la qual construir coses més complexes. Encara que semblin detalls menors, marquen la diferència entre scripts que sobreviuen i projectes que es tornen un problema.