Forum Programmation.python Python: getter, setter, and deleter

Posté par .
2
18
mar.
2011

Bonjour,

L'autre jour, je suis tombé sur ça dans la doc de Python:

class C(object):
    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

class D(C):
    @C.x.getter
    def x(self):
        return self._x * 2

    @x.setter
    def x(self, value):
        self._x = value / 2

Je ne comprend pas bien le sens du @C.x.getter. Pourquoi y a t'il une référence à la classe C ? Quelqu'un pourrait m'expliquer ?

Merci.

  • # Supposition

    Posté par . Évalué à 2.

    Je suppose que c'est pour ne pas « écraser » la propriété de la classe parente. Si tu mettais simplement @property def x(… dans la classe D, tous les « accesseurs » (getter, setter et deleter) de la classe parente disparaîtraient, car ils sont tous associés à la valiable (de classe) x. En particulier, ici, on perdrait le deleter, puisqu'on redéfinit tout de même le getter et le setter.

    Quand tu précises @une_propriété.getter ou autre setter/deleter, la variable contenant la propriété va être écrasée, mais en gardant les accesseurs déjà déclarées, car c'est le décorateur spécifique à la propriété déjà définie auparavant qui est utilisé. Ici, dans la classe D, on utilise le décorateur de la classe C « C.x.getter » pour créer un getter qui conservera les autres accesseurs. Une fois cette propriété définie dans la classe D, on peut l'utiliser pour les accesseurs suivants (ici, le setter de D).

    PS : j'utilise le mot « accesseur » pour désigner aussi bien le getter que le setter et deleter ; je ne trouve pas de meilleur mot.

    • [^] # Re: Supposition

      Posté par . Évalué à 1.

      Merci.

      Du coup, je ne comprend pas pourquoi le @x.setter dans D n'écrase pas la propriété de la classe parente.

      L'exemple est tiré de cette page http://docs.python.org/dev/whatsnew/2.6.html#other-language-changes.

      • [^] # Re: Supposition

        Posté par . Évalué à 1.

        Par ce que après:

        class D(C):
            @C.x.getter
            def x(self):
        

        x existe de nouveau pusique tu as fait un def x. Tu n'as donc plus beoin d'y faire référence via la classe parente.

        Ça peut paraître bizarre, mais c'est du aux contraintes du modèle objet de Python: une classe ne peux pas faire référence à elle même dans sa déclaration. Donc le seul moyen de récupérer la référence de la property original c'est de passer par la référence de la classe mère explicitement.

        • [^] # Re: Supposition

          Posté par . Évalué à 2.

          x existe de nouveau pusique tu as fait un def x. Tu n'as donc plus beoin d'y faire référence via la classe parente.

          Oui. Même si, plus précisément, ici c'est le décorateur qui va au final attribuer la variable x.

          une classe ne peux pas faire référence à elle même dans sa déclaration.

          Oui. Mais on peut tout à fait faire référence aux variables de cette classe déjà définies : c'est ce qu'il se passe avec les décorateurs, ici.

          Donc le seul moyen de récupérer la référence de la property original c'est de passer par la référence de la classe mère explicitement.

          Non. Comme dit au dessus, on peut très bien récupérer les variables déjà définies dans la classe, c'est comme ça que marche ce mécanisme de « chaînage » des décorateurs. Par contre, on ne peut récupérer les variables des classes parentes qu'en mentionnant le parent explicitement. Ce qui est fait ici avec le premier décorateur de la classe D.

          • [^] # Re: Supposition

            Posté par . Évalué à 2.

            Hum je n'ai pas du être assez explicite car j'ai l'impression que tu n'a fait que me paraphraser ....

      • [^] # Re: Supposition

        Posté par . Évalué à 2.

        Du coup, je ne comprend pas pourquoi le @x.setter dans D n'écrase pas la propriété de la classe parente.

        De la même manière que @x.setter n'écrase pas les autres accesseurs dans la classe C. Et de toutes façons, à sa manière, le @C.x.getter a déjà « écrasé » la variable parente (x) au sens où D l'a maintenant redéfinie (mais en gardant les setter et deleter de C).
        Il faut bien comprendre que les trois « accesseurs » dont on parle sont en fait une seule variable python. Pour bien comprendre, il faut déjà bien avoir compris le mécanisme de property, sans les décorateurs : c.f. help(property).
        Quand x.setter est appelé, cette fonction « mémorise » les autres accesseurs déjà définis et ajoute seulement le setter.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.