Le proprietà (property) in Python sono state introdotte come un modo elegante per implementare l'incapsulamento degli attributi, simile ai getter e setter di altri linguaggi (Java/C++), ma senza la necessità di chiamare esplicitamente i metodi. Prima delle proprietà, l'accesso alle variabili doveva essere implementato tramite metodi espliciti get/set, il che complicava e ostruiva l'interfaccia della classe.
Il problema consiste nel fornire all'utente della classe un'interfaccia trasparente per lavorare con gli attributi (utilizzando la notazione a punto obj.x), mentre sotto il cofano si poteva controllare la logica di calcolo, verifica, memorizzazione o validazione dei valori. Senza le proprietà, quando si modifica l'implementazione interna, è necessario cambiare tutte le chiamate, il che porta a errori di massa e riduce l'estensibilità.
La soluzione è che il decoratore @property consente di trasformare un metodo in un attributo, nascondendo la logica di calcolo, verifica o caricamento pigro all'interno dei metodi, senza modificare l'interfaccia esterna della classe. Il getter è implementato solo in lettura, con .setter si organizzano le scritture e .deleter — le cancellazioni.
Esempio di codice:
class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def area(self): # 'area' ora può essere letta come attributo return self._width * self._height @property def width(self): return self._width @width.setter def width(self, value): # chiamato automaticamente quando si assegna rect.width = ... assert value > 0, "Width must be positive" self._width = value rect = Rectangle(3, 4) print(rect.area) # 12 rect.width = 10 print(rect.area) # 40
Caratteristiche chiave:
Può property funzionare con metodi di classe o metodi statici?
No. property funziona solo con proprietà di livello istanza (instance-level). Per le proprietà di livello classe (class-level) utilizzare descrittori speciali o @classmethod-property (implementato manualmente).
Se dichiaro una property solo con getter senza setter, sarà possibile scrivere nell'attributo?
No. Tale property è di sola lettura; il tentativo di assegnazione solleverà un AttributeError.
Cosa succede se all'interno del setter si verifica un'eccezione (ad esempio, assert)?
L'eccezione verrà sollevata all'esterno, l'assegnazione non avverrà e il valore dell'attributo rimarrà invariato. Questo viene spesso utilizzato per la validazione.
Caso negativo: Attributi pubblici della classe, modifica di essi senza controllo.
Vantaggi: veloce, semplice.
Svantaggi: non è possibile modificare la logica interna senza riscrivere il codice del client, possibili stati incoerenti.
Caso positivo: Incapsulamento tramite property, logica in getter/setter, rigorose verifiche.
Vantaggi: flessibilità, controllo, trasparenza, evoluzione API sicura.
Svantaggi: un po' più di codice, lieve complicazione durante il debug.