Partage
  • Partager sur Facebook
  • Partager sur Twitter

liste chainée POO - assigner nouvel objet à self

    24 septembre 2021 à 14:13:58

    Bonjour à toutes et tous

    J'ai créé un objet Liste_chaine instanciée avec 2 attributs (valeur et suivant qui est un objet Liste_chaine).

    class Liste_chaine:  # Objet Liste chainée   
        def __init__ (self, valeur=None, suivant=None):
            self.valeur = valeur
            self.suivant = suivant
    

    La méthode pour ajouter un élément fonctionne avec un return

        def construit (self,element):
            return Liste_chaine(element, self)
    liste = liste.construit(3)

    Mais je préfèrerai utiliser la méthode dans l'esprit des listes chainées, que cela modifie la liste sans renvoyer de valeur, style

        def construit (self,element):
            self = Liste_chaine(element, self)
    liste.construit(3)

    Or cette seconde méthode ne fonctionne pas. L'objet liste n'est pas modifié par la méthode.

    C'est certainement évident pour vous mais moi je cale..

    Comment faire?

    Merci par avance pour vos réponses

    • Partager sur Facebook
    • Partager sur Twitter
      24 septembre 2021 à 14:45:05

      def construit (self,element):
          self.suivant = Liste_chaine(element)
      ?
      • Partager sur Facebook
      • Partager sur Twitter

      "il vaut mieux vivre en France qu'en Italie, la France a de plus jolies prisons"

        24 septembre 2021 à 16:16:42

        Bonjour,

        Merci de la réponse mais. C'est un peu l'inverse pour une liste chainée. Le nouveau "maillon" est inséré en 1ere position. 

        Au départ:    liste = < 1er élément | suivant>       et je souhaite qu'après ma méthode liste.construit(3):  liste =< 3 | liste >

        donc self.valeur = 3 et self.suivant = self

        Mais avec cela mon objet liste n'est pas modifié dans le programme principal. Alors qu'avec la 1ère méthode c'est le cas.

        D'ailleurs en séparant davantage les opérations et en mettant des affichages, je vois bien que quelque chose ne se fait pas correctement:

            def construit (self,element): #
                chainon = Liste_chaine(element, self)
                print("chainon: ", chainon)
                self.valeur = chainon.valeur
                self.suivant = chainon.suivant
                print("self ",self)
        La liste de départ est la liste vide. Cela affiche:
        chainon:  3   [ None ]
        self  3   [ 3...]

         Cela doit être une bêtise mais je ne vois pas. Peut être un conflit de type sur l'attribut suivant

        • Partager sur Facebook
        • Partager sur Twitter
          24 septembre 2021 à 16:28:12

          ca devrait etre:
          def construit (self,element): 
              self.suivant = Liste_chaine(self.valeur, self.suivant)
              self.valeur = element
          • Partager sur Facebook
          • Partager sur Twitter
            24 septembre 2021 à 18:19:35

            Merci beaucoup cela fonctionne!

            En plus je comprends que ce qui clochait dans mon programme.

            self pointe vers la même adresse mémoire avant et après l'application de la méthode. Donc après, je me retrouve avec une liste infinie:

            liste = < 3 | liste >

            Donc toujours recréer un nouvel objet (= nouvelle adresse pour l'objet) avant de reconnecter les morceaux.

            J'y penserai la prochaine fois!! Encore merci!

            • Partager sur Facebook
            • Partager sur Twitter
              24 septembre 2021 à 20:02:47

              LaurentFOUSSADIER1 a écrit:

              self pointe vers la même adresse mémoire avant et après l'application de la méthode. Donc après, je me retrouve avec une liste infinie:

              liste = < 3 | liste >

              hum... si on écrit:

              def construit (self,element):
                  self = Liste_chaine(element, self)

              self n'est que variable locale de la fonction construit. Ca crée une liste qui sera déréférencée à la sortie de la fonction... et ça ne sert à rien.

              LaurentFOUSSADIER1 a écrit:

              Donc toujours recréer un nouvel objet (= nouvelle adresse pour l'objet) avant de reconnecter les morceaux.

              c'est parce que vous ne voulez pas de return...

              • Partager sur Facebook
              • Partager sur Twitter
                8 octobre 2021 à 1:48:03

                mps a écrit:

                hum... si on écrit:

                def construit (self,element):
                    self = Liste_chaine(element, self)

                self n'est que variable locale de la fonction construit. Ca crée une liste qui sera déréférencée à la sortie de la fonction... et ça ne sert à rien.

                LaurentFOUSSADIER1 a écrit:

                Donc toujours recréer un nouvel objet (= nouvelle adresse pour l'objet) avant de reconnecter les morceaux.

                c'est parce que vous ne voulez pas de return...

                Merci de votre réponse.
                Je ne crois pas que self soit une variable locale sinon je n'aurais pas obtenu un chaine qui boucle sur elle même après application de la méthode.

                Je ne voulais pas de return pour rester dans l'esprit du constructeur des listes chainées qui est une procédure et non une fonction. Mais je reconnais que c'est plus simple avec

                • Partager sur Facebook
                • Partager sur Twitter
                  8 octobre 2021 à 2:23:52

                  Tu veux ajouter au début de ta liste et tu ne veut pas de return ?
                  def construit(self, element):
                      apres = Liste_chaine(valeur=self.valeur, suivant=self.suivant)
                      self.valeur = element
                      self.suivant = apres
                  Ça ne marche pas ?

                  edit:

                  J'ai fait un petit test quick and dirty ... Ça marche

                  Pour pouvoir itérer de façon intéressante avec __iter__ il faut à la fois self.valeur=None et self.suivant=None au début.

                  Je n'aime pas trop cela.

                  Ça prendrait une classe de noeuds et une classe de liste qui hériterait de la première.

                  On construit une tête de liste et on y attache les noeuds.

                  C'est plus facile pour ajouter au début ou à la fin et itérer adéquatement.

                  Et on peut avoir une liste vide contrairement à ici.

                  -
                  Edité par PierrotLeFou 8 octobre 2021 à 8:00:47

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Le Tout est souvent plus grand que la somme de ses parties.

                    9 octobre 2021 à 2:47:25

                    Alors, je poste mon code quick and dirty ...
                    -
                    class Noeud:
                        def __init__(self, valeur=None, suivant=None):
                            self.valeur=valeur
                            self.suivant=suivant
                    class Liste(Noeud):
                        def __init__(self):
                            self.nombre = 0
                            self.premier=None
                            self.dernier=None
                        def preceder(self, valeur=None):
                            node = Noeud(valeur=valeur, suivant=self.premier)
                            self.premier=node
                            self.nombre+=1
                        def ajouter(self, valeur=None):
                            node=Noeud(valeur=valeur)
                            if self.dernier is None:
                                self.premier=node
                            else:
                                self.dernier.suivant=node
                            self.dernier=node
                            self.nombre+=1
                        def retirer(self):
                            if self.premier is None:
                                raise ValueError("retirer d'une liste vide")
                            node=self.premier
                            self.premier=self.premier.suivant
                            self.nombre-=1
                            valeur=node.valeur
                            del(node)
                            return valeur
                        def compte(self):
                            return self.nombre
                        def __iter__(self):
                            node=self.premier
                            while node is not None:
                                yield node.valeur
                                node=node.suivant
                    L=Liste()
                    L.ajouter(4)
                    L.preceder(3)
                    L.ajouter(5)
                    for i in L:
                        print(i)
                    for i in range(L.compte()):
                        print(L.retirer())
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Le Tout est souvent plus grand que la somme de ses parties.

                      9 octobre 2021 à 9:10:48

                      LaurentFOUSSADIER1 a écrit:

                      Je ne crois pas que self soit une variable locale sinon je n'aurais pas obtenu un chaine qui boucle sur elle même après application de la méthode.

                      Je respecte vos croyances mais là on parle d'un langage de programmation.

                      le self passé en argument d'une méthode est une variable locale.

                      On peut lui assigner ce qu'on veut dans la méthode, çà ne changera pas l"objet référencé.

                      C'est pareil pour les fonctions:

                      >>> a = 1
                      >>> def f(a):
                      ...     a = 'xx'
                      ...
                      >>> f(a)
                      >>> a
                      1

                      mais ça peut être plus compliqué quand on ajoute des "class" autour:

                      >>> class A:
                      ...    def f(self):
                      ...        print(id(self))
                      ...        self = 123
                      ...
                      >>> a = A()
                      >>> id(a)
                      36623216
                      >>> a.f()
                      36623216
                      >>> id(a)
                      36623216
                      >>>

                      D'où l'intérêt de maîtriser les bases et de prendre l'habitude de tester ses théories avant d'y croire.


                      • Partager sur Facebook
                      • Partager sur Twitter

                      liste chainée POO - assigner nouvel objet à self

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      • Editeur
                      • Markdown