@property

Transforme une méthode en attribut : la valeur est calculée à la lecture, et un setter optionnel contrôle l’écriture.

Sur cette page

Exemple

#
Python
class Student:
    def __init__(self, name, points=0):
        self.name = name
        self.points = points

    @property
    def level(self):
        return self.points // 100 + 1

léa = Student("Léa", 250)
print(léa.level)

léa.points += 100
print(léa.level)

try:
    léa.level = 10
except AttributeError as error:
    print(error)
Résultatrésultat enregistré, vous pouvez le vérifier
3
4
property 'level' of 'Student' object has no setter

Définition et utilisation

#

Le décorateur @property permet de lire une méthode comme un simple attribut, sans parenthèses : student.level au lieu de student.level(). La valeur est calculée à chaque lecture, donc elle correspond toujours à l’état actuel de l’objet, par exemple un niveau calculé à partir des points.

Une propriété sans setter est en lecture seule, et toute tentative d’affectation lève une AttributeError. Pour autoriser une écriture contrôlée, ajoutez une seconde méthode du même nom avec le décorateur @nom.setter. Le setter peut vérifier ou transformer la nouvelle valeur avant de l’enregistrer dans un attribut précédé d’un underscore, par ex. self._points.

Les propriétés permettent de commencer par un attribut ordinaire et d’ajouter une validation plus tard, sans modifier le code qui utilise la classe. C’est pourquoi on n’écrit pas par avance, en Python, des méthodes get_points() et set_points() comme en Java. Le décorateur functools.cached_property mémorise le résultat d’un calcul coûteux qui ne change pas.

Syntaxe

#
Syntaxe
class Nom:
    @property
    def attribut(self):
        return self._attribut

    @attribut.setter
    def attribut(self, valeur):
        self._attribut = valeur

Éléments de la propriété

#
  • @property

    objet.x

    Le getter, la méthode exécutée à la lecture. Son résultat devient la valeur de l’attribut.
  • @x.setter

    objet.x = v

    Le setter, la méthode exécutée lors de l’affectation. Elle reçoit la nouvelle valeur comme paramètre. Sans lui, l’attribut est en lecture seule.
  • @x.deleter

    del objet.x

    La méthode exécutée lors de la suppression de l’attribut. Rarement nécessaire.

Plus d’exemples

#
Un setter avec validation
Python
class Student:
    def __init__(self, name, points=0):
        self.name = name
        self.points = points

    @property
    def points(self):
        return self._points

    @points.setter
    def points(self, value):
        if value < 0:
            raise ValueError("Les points ne peuvent pas être négatifs")
        self._points = value

lucas = Student("Lucas", 40)
lucas.points += 25
print(lucas.points)

try:
    lucas.points = -5
except ValueError as error:
    print(error)

print(lucas.points)
Résultatrésultat enregistré, vous pouvez le vérifier
65
Les points ne peuvent pas être négatifs
65

L’affectation self.points = points dans __init__ passe elle aussi par le setter, donc il est même impossible de créer un objet avec un nombre de points négatif.

Calculé une seule fois : cached_property
Python
from functools import cached_property

class Course:
    def __init__(self, title, lessons):
        self.title = title
        self.lessons = lessons

    @cached_property
    def total_minutes(self):
        print("Calcul de la durée totale...")
        return sum(self.lessons)

python = Course("Python", [15, 20, 25])
print(python.total_minutes)
print(python.total_minutes)
Résultatrésultat enregistré, vous pouvez le vérifier
Calcul de la durée totale...
60
60

Bonnes pratiques

#
  • Une propriété doit s’exécuter rapidement et ne rien modifier. Le lecteur du code suppose que lire un attribut est une opération simple et sûre.
  • Stockez la valeur dans un attribut au nom différent, généralement avec un underscore (self._points). Écrire self.points = value à l’intérieur du setter appellerait ce même setter indéfiniment.
  • Ne créez pas de propriétés par avance. Commencez par un attribut ordinaire et transformez-le en @property quand un besoin de validation ou de calcul apparaît.

Entrées associées

#

Vous voyez une erreur ou il manque un exemple ? Écrivez-nous.