Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Python] propriétés : mutateur non pris en compte

Sujet résolu
    14 juillet 2013 à 12:07:05

    Bonjour,

    Je tente ici l'activité suivante : http://www.siteduzero.com/informatique/tutoriels/apprenez-a-programmer-en-python/les-proprietes-en-action

    >>> class Personne :
    	def __init__(self):
    		self.nom = 'Bernard'
    		self.age = 34
    		self._adresse = 'Paris'
    	def _get_adresse(self):
    		print "On accède à l'attribut adresse."
    		return self._adresse
    	def _set_adresse(self, nouvelleAdresse):
    		print "Attention, l'adresse change. {} est maintenant à {}.".format(nom, nouvelleAdresse)
    		self._adresse = nouvelleAdresse
    	adresse = property(_get_adresse, _set_adresse)
    
    	
    >>> a=Personne()
    >>> a.adresse
    On accède à l'attribut adresse.
    'Paris'
    >>> a.adresse = 'Madrid' # CELA DONNE UNE NOUVELLE VALEUR A L'ATTRIBUT, SANS PASSER PAR LA PROPRIÉTÉ.
    >>> a.adresse
    'Madrid' # APRÈS CA, L'ACCESSEUR N'EST PLUS APPELÉ NON PLUS.
    >>> a._get_adresse()
    On accède à l'attribut adresse.
    'Paris'

    Quand je donne une nouvelle valeur à l'attribut 'a.adresse', on ne passe pas par la propriété '_set_adresse'. Quant à l'accesseur ('_get_adresse'), il était pris en compte avant le changement de valeur de l'attribut, mais ce n'est plus le cas après.

    Merci d'avance !

    PS : Je suis sous Python 3.7, mais j'ai bien consulté la documentation officielle qui décrit précisément la même procédure que dans le cours (le cour décrivant Python 4.x).

    -
    Edité par Kifferand 14 juillet 2013 à 12:08:48

    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      14 juillet 2013 à 12:51:29

      Salut,

      Quand je donne une nouvelle valeur à l'attribut 'a.adresse', on ne passe pas par la propriété '_set_adresse'. Quant à l'accesseur ('_get_adresse'), il était pris en compte avant le changement de valeur de l'attribut, mais ce n'est plus le cas après.

      Tu devrais mettre ton code dans un fichier plutôt que de tout écrire dans l'interpréteur. Je ne saurais pas te dire d'où ça vient, ton code m'a l'air correct, mais comme tu as écrit dans l'interpréteur, je ne peux pas en être sûr.

      PS : Je suis sous Python 3.7, mais j'ai bien consulté la documentation officielle qui décrit précisément la même procédure que dans le cours (le cour décrivant Python 4.x).

      Salut à toi, voyageur du futur ! J'espère que tu viens en paix !

      Plus sérieusement, je déplace ton sujet dans le forum Python, tu auras surement plus de réponses.

      • Partager sur Facebook
      • Partager sur Twitter
        14 juillet 2013 à 13:14:35

        2.7 ! J'ai Python 2.7, bien entendu !

        J'ai encore du boulot avant de pouvoir programmer une machine à voyager dans le temps...

        Merci pour ton aide, mais ça ne marche pas mieux quand j'exécute le code dans un fichier.

        • Partager sur Facebook
        • Partager sur Twitter
          14 juillet 2013 à 13:15:53

          Hello, il me semble qu'après ".format", pour accéder à la valeur "Bernard", il faut que tu écrives "self.nom" et pas seulement "nom".
          • Partager sur Facebook
          • Partager sur Twitter
            14 juillet 2013 à 13:30:42

            Salut, et merci, c'est corrigé. Mais ça ne change pas le problème : la propriété '_set_adresse' n'est pas appelée quand je change la valeur de 'objet.adresse'. Pour l'appeler, je dois faire :

            a._set_adresse("Madrid")
            >>> Attention, l'adresse change. Bernard est maintenant à Madrid.

            Sinon, ça ne marche pas.

            • Partager sur Facebook
            • Partager sur Twitter
              14 juillet 2013 à 13:41:19

              j'ai repris ton code sans rien modifier (j'ai rajouté des parenthèses pour la fonction 'print' parce que je suis sur python 3.3) et il marche:

              >>> a=Personne()
              >>> a.nom
              'Bernard'
              >>> a.adresse
              On accède à l'attribut adresse.
              'Paris'
              >>> a.adresse='Madrid'
              Attention, l'adresse change. Bernard est maintenant à Madrid.
              >>> a.adresse
              On accède à l'attribut adresse.
              'Madrid'
              >>> 



              • Partager sur Facebook
              • Partager sur Twitter
                14 juillet 2013 à 13:59:06

                Bah mince alors... Je ne sais pas quoi dire : je viens de réessayer et toujours rien.

                Je réfléchis...

                • Partager sur Facebook
                • Partager sur Twitter
                  14 juillet 2013 à 14:04:51

                  Je poste le code que j'ai executé au cas où:

                  class Personne :
                      def __init__(self):
                          self.nom = 'Bernard'
                          self.age = 34
                          self._adresse = 'Paris'
                          
                      def _get_adresse(self):
                          print("On accède à l'attribut adresse.")
                          return self._adresse
                      
                      def _set_adresse(self, nouvelleAdresse):
                          print("Attention, l'adresse change. {} est maintenant à {}.".format(self.nom, nouvelleAdresse))
                          self._adresse = nouvelleAdresse
                  
                          
                      adresse = property(_get_adresse, _set_adresse)
                   
                       



                  • Partager sur Facebook
                  • Partager sur Twitter
                    14 juillet 2013 à 14:12:25

                    Etrange... J'ai redémarré mon PC au cas où, et toujours rien...

                    On applique pourtant précisément ce qu'il y a dans la doc officielle.

                    J'ajoute une remarque : lorsque j'attribue une nouvelle valeur à 'objet.adresse', cette valeur n'est pas assignée à '_adresse'. Je me retrouve donc avec :

                    >>> a.adresse = "Madrid"
                    >>> a._adresse
                    'Paris'
                    >>> a.adresse
                    'Madrid'
                    >>> 

                    Sachant que la seule occurrence de l'attribut 'adresse' (sans '_') dans tout ce code, c'est à la ligne :

                    adresse = property(_get_adresse, _set_adresse)

                    c'est visiblement ici qu'on a un problème.

                    Maintenant, j'ajoute la ligne suivante dans les méthodes de Personne :

                    def _del_adresse(self):
                    	    print "On supprime 'adresse'."
                    	    del self._adresse

                    Et je mets les quatre possibilités proposées dans 'help(property)' et dans la doc officielle :

                    adresse = property(_get_adresse, _set_adresse, _del_adresse, "Je suis la propriété 'adresse'.")

                    Résultat : toujours pas d'amélioration, et quand je fais 'del a.adresse', j'obtiens une erreur :

                    Traceback (most recent call last):
                      File "<pyshell#7>", line 1, in <module>
                        del a.adresse
                    AttributeError: Personne instance has no attribute 'adresse'

                    bien que je puisse toujours accéder correctement à 'a.adresse' par l'accesseur après cela.




                    -
                    Edité par Kifferand 14 juillet 2013 à 16:19:47

                    • Partager sur Facebook
                    • Partager sur Twitter
                      14 juillet 2013 à 16:56:11

                      J'ai le même problème que l'auteur du sujet, est-ce la faute à la 2.7 ?


                      Bouture.

                      -
                      Edité par Bouture 14 juillet 2013 à 17:16:46

                      • Partager sur Facebook
                      • Partager sur Twitter
                        14 juillet 2013 à 17:15:37

                        Ce qui est surtout bizarre, c'est que ton code marche sur mon ordinateur et pas sur le tien, puisque c'est avec ton propre code que je peux faire:

                        >>> a=Personne()
                        >>> a.adresse='Madrid'
                        Attention, l'adresse change. Bernard est maintenant à Madrid.
                        >>> a.adresse
                        On accède à l'attribut adresse.
                        'Madrid'
                        >>> a._adresse
                        'Madrid

                        Je crois pas qu'il y ait d'erreur à chercher dans le code, il n'est pas très long et visiblement il n'y a pas d'erreur.

                        Mais alors quoi?

                        ...

                        • Partager sur Facebook
                        • Partager sur Twitter
                          14 juillet 2013 à 17:23:28

                          Je confirme le problème vient effectivement de la version de python 2.7. je l'ai également sur mon ordi et avec toujours le même code j'ai bien le problème que tu as décrit:

                          >>> a=Personne()
                          >>> a.adresse
                          On accède à l'attribut adresse.
                          'Paris'
                          >>> a.adresse='Madrid'
                          >>> a.adresse
                          'Madrid'
                          >>> a._adresse
                          'Paris'
                          >>> 



                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            14 juillet 2013 à 18:44:22

                            Pas le temps de tester, mais si on spécifie les arguments

                            adresse = property(fget=_get_adresse, fset=_set_adresse)

                            ça donne quoi?

                            • Partager sur Facebook
                            • Partager sur Twitter
                              14 juillet 2013 à 19:49:55

                              Chez moi çà donne rien.

                              Le problème est que lorsque l'on met :

                              a.adresse = 'x'

                              c'est celui de la classe ( celui qui vaux property ( ... ) ) qui est modifié.

                              Y aurait pas plutôt un équivalent du self mais qui s'utilise en dehors de la classe ? En fait il s'agirait d'un mot clef qui ne change rien :

                              a.this.this.this == a == a.this # this est un exemple.

                              çà pourrait peut - être dégagé le bug, ainsi a.adresse sera évalué sur celui de l'instance et non celui de la classe.

                              Bouture.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                15 juillet 2013 à 11:33:18

                                fred1599 a écrit:

                                Pas le temps de tester, mais si on spécifie les arguments

                                adresse = property(fget=_get_adresse, fset=_set_adresse)

                                ça donne quoi?

                                Pour moi non plus, ça ne donne rien. Visiblement nous voilà contraints de faire _set_adresse('Madrid'), ainsi que _del_adresse(), et voilà tout.

                                Merci à tous pour vos réponses !

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  15 juillet 2013 à 14:24:23

                                  Non non, suffit juste d'hériter ta classe de la classe object et ça marchera ( au moins avec les décorateurs ).

                                  class Personne ( object ) :
                                      ...

                                  Bouture.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    15 juillet 2013 à 14:28:18

                                    Bouture a écrit:

                                    Non non, suffit juste d'hériter ta classe de la classe object et ça marchera ( au moins avec les décorateurs ).

                                    class Personne ( object ) :
                                    ...

                                    Bouture.

                                    Bon sang, il aura fallu plus de 24h pour que quelqu'un fasse la liaison entre Python 2.7, les properties et le fait qu'elles ne s'appliquent que sur des new-style classes... >_<

                                    C'est évidemment ça la solution.

                                    -
                                    Edité par nohar 15 juillet 2013 à 14:28:54

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Zeste de Savoir, le site qui en a dans le citron !
                                      15 juillet 2013 à 15:46:40

                                      Merci, c'est super !

                                      Maintenant, je vais méditer sur cette histoire d'héritage...

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        15 juillet 2013 à 15:53:20

                                        Kifferand a écrit:

                                        Merci, c'est super !

                                        Maintenant, je vais méditer sur cette histoire d'héritage...

                                        Ne cherche pas trop loin, c'est juste un détail de conception du langage.

                                        En Python 2 tu as deux types de classes : les classes old-style, et les classes new-style. Pour être une classe new-style en Python 2, il suffit d'hériter d'une autre classe new-style, et object en est justement une (c'est même précisément la mère de toutes les classes new-style). En Python 3, toutes les classes héritent par défaut de la classe object, donc elles sont toutes new-style. Quant aux properties, celles-ci ne fonctionnent que sur les classes new-style.

                                        -
                                        Edité par nohar 15 juillet 2013 à 15:55:09

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Zeste de Savoir, le site qui en a dans le citron !
                                          19 juillet 2013 à 9:19:36

                                          Merci, par ailleurs, en avançant dans le cours, j'en ai découvert la partie sur l'héritage qui éclaircit pas mal la situation.
                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          [Python] propriétés : mutateur non pris en compte

                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                          • Editeur
                                          • Markdown