In Python, il decoratore @property consente di creare attributi "virtuali" — metodi che sembrano e vengono usati come normali campi, ma eseguono la logica del getter, setter o deleter. Questo è utile per creare proprietà calcolate o per controllare l'accesso ai dati.
Esempio:
class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def area(self): return self._width * self._height @property def width(self): return self._width @width.setter def width(self, value): if value <= 0: raise ValueError('La larghezza deve essere positiva') self._width = value r = Rectangle(3, 4) print(r.area) # 12 (viene chiamato come proprietà, non come funzione) r.width = 10 # setter chiamato automaticamente
Si può utilizzare solo un @property (metodo get) senza definire un setter? Cosa succede se si prova a modificare tale attributo?
Risposta: È possibile definire solo il getter @property senza il setter (e il deleter). Tale attributo sarà di sola lettura, e tentare di assegnarlo genererà un AttributeError.
class C: @property def x(self): return 42 c = C() c.x = 99 # AttributeError: impossibile impostare l'attributo
Storia
Si è cercato di serializzare un oggetto utilizzando la libreria standard, usando vars(obj) per ottenere un dizionario di attributi. Si è scoperto che i metodi di property non fanno parte dell'uscita di __dict__, i loro valori non sono stati serializzati, portando a una fuga di dati.
Storia
Nel progetto si è dimenticato di aggiungere un setter per la property, di conseguenza il tentativo di modificare il valore di un campo calcolato portava a un errore di runtime, anche se per logica architettonica ci si aspettava.
Storia
Nel codice funzionante, il calcolo del valore della property consentiva operazioni pesanti o non sicure, che venivano inaspettatamente invoke ad ogni accesso alla proprietà. Questo ha ridotto le prestazioni e ha portato a chiamate bloccanti nel codice multithreading.