Qu'est-ce qu'une propriété en Python ?

Les propriétés permettent de définir des comportements de 'getter' et 'setter' sur les méthodes d'une classe.

Cela nous permet également d'appeler une méthode sans avoir besoin d'utiliser les parenthèses.

Pour créer une propriété de type get, on utilise le décorateur @property sur une méthode :

class CompteBancaire:

    @property
    def numero(self):
        return "83947382738"

compte = CompteBancaire()

# On peut accéder à la valeur retournée par la méthode numero sans utiliser les parenthèses
print(compte.numero)

En l'état, notre propriété est en lecture seule. Comme nous n'avons pas défini de 'setter', il est impossible de modifier cet attribut :

class CompteBancaire:

    @property
    def numero(self):
        return "83947382738"

compte = CompteBancaire()
compte.numero = "123456789"  # AttributeError: can't set attribute on line 24

Pour rajouter un 'setter', il faut décorer la méthode du même nom avec un décorateur avec la syntaxe @method.setter :

class CompteBancaire:
    def __init__(self):
        self._numero = "83947382738"

    @property
    def numero(self):
        return self._numero

    @numero.setter
    def numero(self, value):
        self._numero = value

compte = CompteBancaire()
compte.numero = "123456789"
print(compte.numero)

Dans ce cas, on utilise donc le décorateur @numero.setter sur la méthode numero.

Nous rajoutons également un attribut privé (self._numero) qui n'est donc pas destiné à être manipulé directement.

Cela permet notamment de changer en interne le nom de notre attribut sans que cela impacte des utilisateurs potentiels de notre classe (on pourrait renommer self._numero par self._identifiantet laisser le nom des méthodes tel quel).

Le 'setter' nous permet également de rajouter un peu de logique lors de la modification d'un attribut.

Par exemple, nous pouvons vérifier si la nouvelle valeur donnée au numéro du compte ne contient que des nombres (et lever une erreur si ce n'est pas le cas) :

class CompteBancaire:
    def __init__(self):
        self._numero = "83947382738"

    @property
    def numero(self):
        return self._numero

    @numero.setter
    def numero(self, value):
        if value.isdigit():
            self._numero = value
        else:
            raise ValueError("Le numéro du compte ne peut contenir que des chiffres.")

compte = CompteBancaire()
compte.numero = "123456789"  # Fonctionne
compte.numero = "abcdefghi"  # ValueError