Variabili di classe e di istanza

Distinzione tra variabili di classe e di istanza spiegata.

Rachit Tayal
Rachit Tayal

Follow

Jun 9, 2019 – 3 min read

Le variabili sono essenzialmente simboli che stanno per un valore che stiamo usando in un programma. La programmazione orientata agli oggetti permette di usare le variabili a livello di classe o di istanza. Lo scopo di questo articolo è di avere una chiara distinzione tra i tipi di variabili offerti dal modello a oggetti di Python e va avanti per discutere ulteriormente un comportamento peculiare che potrebbe portare a risultati sorprendenti, se trascurato. Quindi scaviamo!
Come da modello a oggetti di Python, ci sono due tipi di attributi di dati sugli oggetti Python: variabili di classe e variabili di istanza.

Variabili di classe – Dichiarate all’interno della definizione della classe (ma fuori da qualsiasi metodo di istanza). Non sono legate a nessun oggetto particolare della classe, quindi sono condivise da tutti gli oggetti della classe. La modifica di una variabile di classe ha effetto su tutti gli oggetti istanza allo stesso tempo.

Variabile d’istanza – Dichiarata all’interno del metodo costruttore della classe (il metodo __init__). Sono legate all’istanza particolare dell’oggetto della classe, quindi il contenuto di una variabile di istanza è completamente indipendente da un’istanza dell’oggetto all’altra.

Iniziamo con un esempio breve e facile da digerire:

class Car:
wheels = 4 # <- Class variable def __init__(self, name):
self.name = name # <- Instance variable

Qui sopra è definita la classe Car di base, senza fronzoli. Ogni istanza di essa avrà le ruote della variabile di classe insieme al nome della variabile di istanza. Istanziamo la classe per accedere alle variabili.

>>> jag = Car('jaguar')
>>> fer = Car('ferrari')>>> jag.name, fer.name
('jaguar', 'ferrari')>>> jag.wheels, fer.wheels
(4, 4)>>> Car.wheels
4

Accedere al nome della variabile di istanza è abbastanza semplice. Tuttavia c’è un po’ più di flessibilità quando si tratta di accedere alla variabile di classe. Come sopra, possiamo accedere alle ruote attraverso l’istanza dell’oggetto o la classe stessa.

Anche il tentativo di accedere al nome attraverso la classe risulterà in un AttributeError poiché le variabili di istanza sono specifiche dell’oggetto e vengono create quando viene invocato il __init__costruttore. Questa è la distinzione centrale tra le variabili di classe e di istanza.

>>> Car.name
AttributeError: type object 'Car' has no attribute 'name'

Ora, assumiamo per il momento che la nostra auto Jaguar abbia 3 ruote. (sì, è stupido ma abbiate pazienza!!! 😅). Per rappresentarlo nel nostro codice, possiamo modificare la variabile wheels.

>>> Car.wheels = 3

Quello che abbiamo fatto sopra renderà tutte le auto con 3 ruote poiché abbiamo modificato una variabile di classe, che si applicherà a tutte le istanze della classe Car.

>>> jag.wheels, fer.wheels
(3, 3)

Quindi la modifica di una variabile di classe nello spazio dei nomi della classe ha effetto su tutte le istanze della classe. Riportiamo indietro la modifica e modifichiamo la variabile wheels usando l’oggetto jag.

>>> Car.wheels = 4
>>> jag.wheels = 3

Questo ci darà l’output che desideriamo.

>>> jag.wheels, fer.wheels, Car.wheels
(3, 4, 4)

Anche se abbiamo ottenuto il risultato che volevamo, ma quello che è successo dietro le quinte è una nuova variabile wheels che è stata aggiunta all’oggetto jag e questa nuova variabile mette in ombra la variabile di classe con lo stesso nome, sovrascrivendola e nascondendola. Possiamo accedere a entrambe le variabili delle ruote come segue.

>>> jag.wheels, jag.__class__.wheels
(3, 4)

Da qui possiamo concludere che jag.wheels = 3 ha creato una nuova variabile di istanza con lo stesso nome della variabile di classe (ruote). Questo è un concetto importante di cui essere consapevoli.
Facendo uso di variabili specifiche di classe e di istanza può assicurare che il nostro codice aderisca al principio DRY per ridurre la ripetizione nel codice.
Secondo me, sapere questo può essere molto utile e risparmiare molte ore di debugging un giorno. 😇
Riferimento a questo mio post per ulteriori letture sui vari tipi di metodi (istanza, classe & statici) in Python.

Conclusioni

  • Le variabili di classe sono condivise tra tutti gli oggetti mentre le variabili di istanza sono per dati unici per ogni istanza.
  • La variabile di istanza sovrascrive le variabili di classe che hanno lo stesso nome e che possono accidentalmente introdurre bug o comportamenti sorprendenti nel nostro codice.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.