@property est un décorateur intégré en langage python qui est utilisé pour faire en sorte que des fonctions telles que les getters et les setters dans une classe se comportent comme des propriétés de classe.

@property

Le décorateur python @property permet d’accéder à une méthode en tant qu’attribut plutôt qu’en tant que méthode ou fonction.

Les getters : des méthodes qui aident à accéder aux attributs privés.
Les setters : des méthodes qui change ou définissent la valeur des attributs privés.

Mais pourquoi est-il vraiment nécessaire et dans quelles situations pouvez-vous l’utiliser ?

En Python, tous les attributs et méthodes sont publics, il est donc inutile d’écrire des getters ou des setters.

Si vous souhaitez empêcher l’accès direct à un attribut, vous devez le définir en tant que propriété. C’est un moyen simple pour personnaliser l’accès à un attribut.

Créons une classe Etudiant, dans laquelle on a 3 propriétés, à savoir nom_famille, prenom et nomcomplet, qui est une concaténation des deux premières propriétés.

Et nous avons aussi une fonction, email() qui génère une adresse e-mail en utilisant le prénom et le nom.

class Etudiant:
	def __init__(self, nom_famille, prenom):
		self.nom_famille = nom_famille
		self.prenom = prenom
		self.nomcomplet = self.prenom +' '+ self.nom_famille

	# générer un email avec le nom de famille et le prénom
	def email(self):
		return f'{self.prenom}.{self.nom_famille}@python.com'

À présent, nous allons créer quelques objets et appeler la fonction email() et essayons quelques trucs.

# Étudiant E1
E1 = Etudiant('Richard', 'Marie')
print('Le nom complet de E1 est :', E1.nomcomplet)
print('Addresse email = ', E1.email())

# modifier le nom de l'objet E1
E1.nom_famille = 'Bernard'
print('Le nom complet de E1 est :', E1.nomcomplet)
print('Addresse email = ', E1.email())

L’exécution du code.

Le nom complet de E1 est : Marie Richard
Addresse email =  Marie.Richard@python.com
Le nom complet de E1 est : Marie Richard
Addresse email =  Marie.Bernard@python.com

Dans la classe Etudiant, le prénom et le nom de famille sont des attributs. Le nom complet et l’e-mail sont des attributs formés à partir d’autres attributs.

Ici, nomcomplet est une variable et email() est une fonction.

Le changement du prénom a modifié l’e-mail, mais le nom complet n’a pas changé.
C’est parce que email()est une fonction qui est appelée au moment où nous voulons que l’e-mail soit renvoyé, tandis que nomcomplet est défini au moment de l’initialisation de l’objet.

Pour résoudre ce problème, vous pouvez créer une fonction qui renvoie le nom complet. Mais attention, cela affectera le code dans tous les fichiers qui ont déjà utilisé la classe.

De plus, créer une fonction n’est pas la manière pythonique pour résoudre ce problème.

L’utilisation de @property

Nous allons utiliser @property dans le programme ci-dessus pour résoudre le problème de nomcomplet en créant une fonction getter pour nomcomplet qui lui permettra d’être utilisé comme une simple variable et retournera toujours sa valeur modifiée. N’oubliez pas d’enlever l’attribut nomcomplet.

class Etudiant:
	def __init__(self, nom_famille, prenom):
		self.nom_famille = nom_famille
		self.prenom = prenom

	@property
	def nomcomplet(self):
		return self.prenom +' '+ self.nom_famille

	# générer un email avec le nom de famille et le prénom
	def email(self):
		return f'{self.prenom}.{self.nom_famille}@python.com'

# Étudiant E1
E1 = Etudiant('Richard', 'Marie')
print('Le nom complet de E1 est :', E1.nomcomplet)
print('Addresse email = ', E1.email())

# nous allons modifier le nom de l'objet E1
print("\nLa modification : ")
E1.nom_famille = 'Bernard'
print('Le nom complet de E1 est :', E1.nomcomplet)
print('Addresse email = ', E1.email())

Remarquez l’utilisation de E1.nomcomplet au lieu de E1.nomcomplet().

L’exécution du code :

Le nom complet de E1 est : Marie Richard
Addresse email =  Marie.Richard@python.com

La modification : 
Le nom complet de E1 est : Marie Bernard
Addresse email =  Marie.Bernard@python.com

Dans l’exemple ci-dessus, le décorateur @property est utilisé avec la fonction nomcomplet(). Maintenant, cette fonction fonctionnera comme un attribut et peut également fonctionner comme un getter à cause du décorateur @property.

Définir des méthodes setter et deleter avec @property

La méthode setter définira la valeur de l’attribut et la méthode deleter supprimera l’attribut de la mémoire.

class Etudiant:
	def __init__(self, nom_famille, prenom):
		self.nom_famille = nom_famille
		self.prenom = prenom

	@property
	def nomcomplet(self):
		return self.prenom +' '+ self.nom_famille

	# définir nomcomplet
	@nomcomplet.setter
	def nomcomplet(self, nom):
		# découper le nom
		prenom, nom_famille = nom.split(" ")
		self.prenom = prenom
		self.nom_famille = nom_famille

	# supprimer nomcomplet
	@nomcomplet.deleter
	def nomcomplet(self):
		self.prenom = None
		self.nom_famille = None
		print('Suppression du nom')

	def email(self):
		return f'{self.prenom}.{self.nom_famille}@python.com'

# Étudiant E1
E1 = Etudiant('Richard', 'Marie')
print('Le nom complet de E1 est :', E1.nomcomplet)
print('Addresse email = ', E1.email())

# nous allons modifier le nom de l'objet E1
E1.nom_famille = 'Bernard'
print('Le nom complet de E1 est :', E1.nomcomplet)
print('Addresse email = ', E1.email())

# créer une nouvelle valeur pour nomcomplet
E1.nomcomplet = 'Lucie Martinez'
print('Le nouveau nom est : ', E1.nomcomplet)

# supprimer le nom
del E1.nomcomplet

L’exécution du code.

Le nom complet de E1 est : Marie Richard
Addresse email =  Marie.Richard@python.com
Le nom complet de E1 est : Marie Bernard
Addresse email =  Marie.Bernard@python.com
Le nouveau nom est :  Lucie Martinez
Suppression du nom

Dans l’exemple ci-dessus, nous avons créé un getter, un setter et un deleter à l’aide du décorateur @property.
On a utilisé les décorateurs @nomcomplet.setter et @nomcomplet.deleter (nomcomplet est le nom de notre fonction à décorer).

La fonction property()

Au lieu d’utiliser un @property, nous pouvons utiliser la fonction property() en python pour créer des getters, des setters et des deleters. Elle renvoie l’attribut de propriété à partir du getter, du setter et du deleter donnés.

La syntaxe est : property(fget, fset, fdel, doc)

fget() : obtenir la valeur de l’attribut.
fset() : définir la valeur d’un attribut.
fdel() : supprimer la valeur d’attribut.
doc() : une chaîne contenant la documentation (docstring) de l’attribut.

class Etudiant:
	def __init__(self, nom_famille, prenom):
		self.nom_famille = nom_famille
		self.prenom = prenom

	def nomcomplet_getter(self):
		return self.prenom +' '+ self.nom_famille

	def nomcomplet_setter(self, nom):
		prenom, nom_famille = nom.split(" ")
		self.prenom = prenom
		self.nom_famille = nom_famille

	def nomcomplet_deleter(self):
		self.prenom = None
		self.nom_famille = None
		print('Suppression du nom')

	def email(self):
		return f'{self.prenom}.{self.nom_famille}@python.com'

	nomcomplet = property()
	nomcomplet = nomcomplet.getter(nomcomplet_getter)
	nomcomplet = nomcomplet.setter(nomcomplet_setter)
	nomcomplet = nomcomplet.deleter(nomcomplet_deleter)

	# cela peut également être fait en une seule ligne
    # nomcomplet = property(nomcomplet_getter, nomcomplet_setter, nomcomplet_deleter)

# Étudiant E1
E1 = Etudiant('Richard', 'Marie')
print('Le nom complet de E1 est :', E1.nomcomplet)
print('Addresse email = ', E1.email())

# nous allons modifier le nom de l'objet E1
E1.nom_famille = 'Bernard'
print('Le nom complet de E1 est :', E1.nomcomplet)
print('Addresse email = ', E1.email())

# créer une nouvelle valeur pour nomcomplet
E1.nomcomplet = 'Lucie Martinez'
print('Le nouveau nom est : ', E1.nomcomplet)

# supprimer le nom
del E1.nomcomplet

L’exécution du code.

Le nom complet de E1 est : Marie Richard
Addresse email =  Marie.Richard@python.com
Le nom complet de E1 est : Marie Bernard
Addresse email =  Marie.Bernard@python.com
Le nouveau nom est :  Lucie Martinez
Suppression du nom

Il est recommandé d’utiliser le décorateur @property qui facilite la déclaration d’une propriété au lieu d’appeler la fonction property().

@Property est un décorateur intégré pour la fonction property() en Python. Il est utilisé pour ajouter des fonctionnalités « spéciales » à certaines méthodes pour les faire agir comme des getters, des setters ou des deleters lorsque nous définissons des propriétés dans une classe.

En définissant des propriétés, vous pouvez modifier une classe sans affecter le programme. Donc, vous pouvez ajouter des getters, des setters et des deleters qui agissent en arrière-plan pour éviter d’accéder ou de modifier directement les données.


1 commentaire

edgard floor · 23 mai 2022 à 16 h 09 min

Je suis tombé sur une ligne @property en lisant un bon tutoriel sur tkinter, j’ai voulu comprendre de quoi il en retournait et votre article m’y a beaucoup aidé. Malgré tout, j’ai toujours du mal à comprendre dans quelle situation utiliser property, ses getters, ses deleters, est indispensable, ou du moins souhaitable. Dans celle que vous décrivez, on comprend qu’en Python, qu’il n’est pas très malin de créer un attribut à partir de deux autres.

Laisser un commentaire

Emplacement de l’avatar

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *