lettura facile

Le proprietà di una classe in Python

Parliamo delle proprietà di una classe in Python. Le proprietà sono attributi delle classi che contengono dei valori, informazione o altro.

Qual è la differenza tra le proprietà e i metodi? Le proprietà e i metodi sono entrambi attributi della classe ma c'è un'importante differenza. Le proprietà sono utilizzate per controllare l'accesso agli attributi informativi di una classe. Ad esempio, nella classe "automobili" una proprietà potrebbe essere il "colore" dell'auto. D'altra parte, invece, i metodi sono funzioni associate alla classe che definiscono comportamenti e operazioni che gli oggetti di quella classe possono eseguire. Ad esempio, nella classe "automobili" un metodo potrebbe essere un'azione specifica come "svolta_a_destra()".

In Python, le proprietà funzionano come degli attributi non chiamabili.

Puoi usarle per memorizzare i dati degli oggetti che hai creato tramite la classe.

Esistono degli appositi metodi che ti permettono di accedere al valore di un proprietà (getter) e di modificarlo (setter).

In realtà Python ammette anche delle proprietà chiamabili che di fatto sono metodi con le sembianze di una proprietà, ma di questo parleremo in un apposito approfondimento sulle classi.

Facciamo un esempio pratico.

Supponiamo di avere una classe `Persona` con due proprietà: `nome` ed `età`.

class Persona:
    def __init__(self, nome, eta):
         self.nome = nome
         self.eta = eta

Una volta definita la classe, puoi creare degli oggetti (istanze) della classe.

Ad esempio, crea un oggetto 'Studente' indicando il valore "Mario" come nome e il valore 30 come 'eta'.

Studente = Persona("Mario",30)

Ora puoi accedere a ogni proprietà dell'oggetto, indicando il nome dell'oggetto seguito da un punto di separazione e dal nome della proprietà.

Ad esempio, per accedere alla proprietà `età` puoi scrivere:

print(Studente.eta)

30

Per definire un attributo privato è comune precedere il nome dell'attributo con un underscore per indicare che non dovrebbe essere accesso direttamente.

Ad esempio, modifica la classe precedente indicando la proprietà `età` come `_età`.

class Persona:
    def __init__(self, nome, eta):
         self.nome = nome
         self._eta = eta

    @property
    def eta(self):
         """Getter per l'età."""
         return self._eta

Studente = Persona("Mario", 30)
print(Studente.eta)

In questo esempio `_eta` è un attributo "privato" che usiamo per immagazzinare il valore dell'età

La proprietà `eta`, definita con il decoratore `@property`, rende possibile ottenere il valore di `_eta` tramite un metodo getter.

Il risultato finale è sempre lo stesso.

30

L'uso di @property ha diversi vantaggi. Ad esempio ti permette l'incapsulamento. In questo modo le proprietà nascondono i dettagli di implementazione e espongono solo una interfaccia sicura. In questo modo, puoi cambiare l'implementazione senza dover modificare il codice che usa la classe.

A questo punto vorremmo assicurarci che l'età non sia mai negativa.

Per farlo possiamo definire un metodo setter che controlla la modifica della proprietà `_età`. 

class Persona:
    def __init__(self, nome, eta):
         self.nome = nome
         self._eta = eta

    @property
    def eta(self):
         """Getter per l'età."""
         return self._eta

    @eta.setter
    def eta(self, value):
         """Setter per l'età che impedisce valori negativi."""
         if value < 0:
              raise ValueError("L'età non può essere negativa.")
         self._eta = value

Studente = Persona("Mario", 30)
Studente.eta=-30
print(Studente.eta)

In questo modo possiamo creare un oggetto `Persona` e interagire con `eta` come se fosse un attributo normale, ma con i controlli aggiunti.

Ad esempio, se proviamo a modificare l'età con un valore negativo, la classe solleva un'eccezione.

L'età non può essere negativa.

Come visto nell'esempio, l'aver definito un metodo setter per la proprietà `eta` ti permette di validare i dati prima che vengano realmente impostati.

Il metodo setter è utile anche quando  hai un attributo che richiede un calcolo complesso. Puoi usarlo con una proprietà che calcola il valore solo quando è necessario. Ad esempio, quando modifichi la proprietà `eta` puoi aggiornare un altro attributo della classe che calcola gli anni mancanti alla pensione.

class Persona:
    def __init__(self, nome, eta):
         self.nome = nome
         self._eta = eta

    @property
    def eta(self):
         """Getter per l'età."""
         return self._eta

    @eta.setter
    def eta(self, value):
         """Setter per l'età che impedisce valori negativi."""
         if value < 0:
              raise ValueError("L'età non può essere negativa.")
         self._eta = value
         # Aggiorna un altro attributo legato quando l'età cambia
         self._anni_alla_pensione = 65 - self._eta if self._eta < 65 else 0

Studente = Persona("Mario", 30)
print(Studente.eta)

In generale le proprietà in Python sono uno strumento potente che ti permette di scrivere codice più sicuro e mantenibile.

Imparare a utilizzarle correttamente può migliorare notevolmente la progettazione delle tue classi.

 




Se qualcosa non ti è chiaro, scrivi la tua domanda nei commenti.




FacebookTwitterLinkedinLinkedin