La funzione property in Python permette di assegnare fa­cil­men­te valori agli attributi da una classe Python. I relativi metodi getter o setter vengono chiamati au­to­ma­ti­ca­men­te.

Cos’è esat­ta­men­te la funzione property in Python e a cosa serve?

In Python, le proprietà sono un costrutto di pro­gram­ma­zio­ne che gli svi­lup­pa­to­ri e le svi­lup­pa­tri­ci possono usare nella pro­gram­ma­zio­ne orientata agli oggetti, definendo metodi ai quali poi accedere come agli attributi. Per­met­to­no un accesso più intuitivo agli attributi di una classe, rendendo tra l’altro superfluo chiamare metodi setter e getter dedicati. Le proprietà in Python tra­sfor­ma­no gli attributi delle classi in proprietà chiamate “attributi gestiti”.

Inoltre, una proprietà in Python realizza una sorta di controllo degli accessi: permette di as­si­cu­ra­re che altri metodi non accedano fa­cil­men­te ai dati dell’attributo e non possano mo­di­fi­car­li in modo in­de­si­de­ra­to.

Consiglio

Se uti­liz­za­te Python per rea­liz­za­re un progetto web, vale la pena di dare uno sguardo anche a Deploy Now. Questo pratico strumento vi permette di compilare e di­stri­bui­re il vostro codice di­ret­ta­men­te tramite GitHub, au­men­tan­do enor­me­men­te l’ef­fi­cien­za del flusso di lavoro.

La funzione property() in Python

Per uti­liz­za­re le proprietà, gli svi­lup­pa­to­ri e le svi­lup­pa­tri­ci possono servirsi della funzione property() in Python. Si tratta di una funzione integrata uti­liz­za­bi­le senza dover importare ulteriori moduli. La funzione property() stessa è im­ple­men­ta­ta nel lin­guag­gio di pro­gram­ma­zio­ne C, ga­ran­ten­do pre­sta­zio­ni ottimali.

La sintassi della funzione property() in Python si presenta come segue:

property(fget=None, fset=None, fdel=None, doc=None)
Python

I parametri della funzione property() sono opzionali. Nella tabella seguente potete scoprire il si­gni­fi­ca­to dei singoli parametri:

Parametro Si­gni­fi­ca­to
fget Funzione che re­sti­tui­sce il valore dell’attributo (metodo getter)
fset Funzione che permette di impostare il valore dell’attributo (metodo setter)
fdel Funzione che indica come deve essere eliminato l’attributo
doc Stringa Python che descrive la proprietà

Il de­co­ra­to­re property in Python

Non è stret­ta­men­te ne­ces­sa­rio uti­liz­za­re la funzione property() per lavorare con le proprietà. Spesso si ricorre a un de­co­ra­to­re Python pre­de­fi­ni­to che permette di uti­liz­za­re un metodo della classe come property. Il lin­guag­gio di pro­gram­ma­zio­ne supporta tre de­co­ra­to­ri diversi con la famosa notazione @ per per­met­ter­vi di definire una proprietà:

  • @property: definisce un metodo della vostra classe come property Python
  • @property-name.setter: specifica un metodo setter che imposta il valore di una proprietà
  • @property-name.deleter: specifica il metodo che elimina una proprietà.
N.B.

Se siete in­te­res­sa­ti o in­te­res­sa­te a tutorial di Python avanzati, vi con­si­glia­mo di con­sul­ta­re gli articoli seguenti:

Esempio di property in Python

Per il­lu­stra­re il fun­zio­na­men­to e l’utilità della funzione property in Python ri­cor­ria­mo a un esempio di codice. Nella sezione di codice che segue, per prima cosa si crea una classe chiamata “cane” con l’attributo “_name”. No­no­stan­te questo esempio sia ef­fet­ti­va­men­te piuttosto ar­ti­fi­cia­le e non abbia una reale utilità, è perfetto per mostrare il fun­zio­na­men­to delle proprietà in Python.

class cane:
	def __init__(self):
		self._name = "Fido"
Python

Come potete vedere, al co­strut­to­re non viene passato nessun parametro che specifica il nome del nostro cane. L’im­po­sta­zio­ne pre­de­fi­ni­ta è “Fido”. Potete dunque creare un oggetto della classe, ad esempio con la riga di codice seguente:

cane = cane()
Python

Metodi getter e setter

Potete ampliare la vostra classe con metodi getter e setter specifici. È utile farlo per diversi motivi, ma qui sot­to­li­neia­mo so­prat­tut­to la facilità di ma­nu­ten­zio­ne del codice e l’in­te­gra­zio­ne di fun­zio­na­li­tà ag­giun­ti­ve. Siccome per im­po­sta­zio­ne pre­de­fi­ni­ta i nomi sono stringhe, nella nostra classe vogliamo anche as­si­cu­rar­ci che sia ef­fet­ti­va­men­te passato un nome sotto forma di stringa. A questo scopo scriviamo la relativa logica di fun­zio­na­men­to in un metodo setter dedicato e ampliamo la de­fi­ni­zio­ne della classe sopra:

class cane:
	def __init__(self):
		self._name = "Fido"
	
	def getName(self):
		return self._name
	def setName(self, name):
		if isinstance(name, str):
			self._name = name
		else:
			return
Python

Nel metodo setter chiamato “setName”, con un’istru­zio­ne if-else in Python si verifica se il parametro passato è una stringa. Se lo è, viene impostato il nome, al­tri­men­ti non succede nulla.

Abbiamo inoltre spe­ci­fi­ca­to un metodo getter che re­sti­tui­sce il nome del cane.

Possiamo creare un oggetto della nostra classe con il nome “Lassie” come segue:

lassie = cane()
lassie.setName("Lassie")
print(lassie.getName())
Python

L’output si presenta come segue, quindi come de­si­de­ra­to:

'Lassie'
N.B.

A dif­fe­ren­za di altri linguaggi di pro­gram­ma­zio­ne, Python non prevede la pos­si­bi­li­tà di dif­fe­ren­zia­re tra gli attributi di classe che possono essere usati dall’esterno di­ret­ta­men­te, senza metodi getter o setter (in altri linguaggi questi attributi sono spesso definiti “public”), e quelli che non possono essere mo­di­fi­ca­ti fa­cil­men­te dall’esterno (in altri linguaggi “private”). Pertanto, con­ven­zio­nal­men­te gli attributi dei nomi delle variabili che non devono essere usati senza metodi getter e setter iniziano con un carattere di sot­to­li­nea­tu­ra.

La funzione property() in Python

Per evitare di chiamare espli­ci­ta­men­te una funzione allo scopo di mo­di­fi­ca­re o scoprire il nome del cane in Python, ci serviamo ora della funzione property. A fini di­mo­stra­ti­vi inseriamo anche un’istru­zio­ne print nel nostro metodo getter e setter.

class cane:
	def __init__(self):
		self._name = "Fido"
	def getName(self):
		print("metodo getter chiamato")
		return self._name
	def setName(self, name):
		if isinstance(name, str):
			self._name = name
			print("metodo setter chiamato")
		else:
			return
	
	name = property(getName, setName)
Python

Come potete vedere, per chiamare la funzione property() non abbiamo dovuto fare nient’altro che creare un nuovo attributo chiamato “name” (questa volta non preceduto dal carattere di sot­to­li­nea­tu­ra, perché grazie alla property Python la funzione può essere chiamata fa­cil­men­te dall’esterno) e assegnare a esso il risultato della chiamata di funzione. Come parametro, la funzione property() riceve i già noti metodi getter e setter.

A questo punto, creando un ulteriore oggetto della classe con il nome “Snoopy”, vedete subito la dif­fe­ren­za:

snoopy = cane()
snoopy.name = "Snoopy"
snoopy.name
Python

Ora si può accedere fa­cil­men­te agli attributi della classe con la notazione con punto. È in­te­res­san­te in par­ti­co­la­re l’output del programma:

Metodo setter chiamato
Metodo getter chiamato
'Snoopy'

Anche se non sono stati chiamati espli­ci­ta­men­te, i metodi getter e setter sono stati eseguiti al momento dell’as­se­gna­zio­ne o dell’in­ter­ro­ga­zio­ne del nome dell’oggetto “Snoopy” mediante la notazione con punto. Questo grazie alla funzione property in Python.

Il de­co­ra­to­re property in Python

Potete ottenere lo stesso effetto con i già men­zio­na­ti de­co­ra­to­ri di funzioni. In questo caso, il codice di esempio si presenta come segue (at­ten­zio­ne: ora i due metodi decorati devono avere lo stesso nome):

class cane:
	def __init__(self):
		self._name = "Fido"
	@property
	def name(self):
		print("metodo setter chiamato")
		return self._name
	@name.setter
	def name(self, name):
		if isinstance(name, str):
			self._name = name
			print("metodo getter chiamato")
		else:
			return
Python

Di nuovo, potete creare un oggetto della vostra classe e impostare e se­le­zio­na­re l’attributo “name” mediante la notazione con punto.

tintin = cane()
tintin.name = "Tintin"
tintin.name
Python

Rispetto a quando abbiamo usato la funzione property() in Python, l’output non è cambiato:

Metodo setter chiamato
Metodo getter chiamato
'Tintin'
Vai al menu prin­ci­pa­le