Partage
  • Partager sur Facebook
  • Partager sur Twitter

J'essaie de comprendre

    2 janvier 2024 à 13:56:41

    class Probleme:
        def __init__(self,tableau1,tableau2):
            self.tableau1 = tableau1
            self.tableau1bis = tableau1
            self.tableau2=tableau2
        def __str__(self):
            print("tableau1 =", self.tableau1)
            print("tableau1bis =", self.tableau1bis)
            print("tableau2 =", self.tableau2)
            return ""
        def completer(self,a):
            self.tableau1.append(a)
    probleme=Probleme([36,42],[10,12])
    print(probleme)
    probleme.completer(5)
    print(probleme)
        

    Le code précédent donne à l'exécution:

    tableau1 = [36, 42]
    tableau1bis = [36, 42]
    tableau2 = [10, 12]
    
    tableau1 = [36, 42, 5]
    tableau1bis = [36, 42, 5]
    tableau2 = [10, 12]
    
    

    Pourquoi, diantre, le tableau1bis a-t-il été modifié par ma méthode? Quelqu'un peut-il m'éclairer?

    • Partager sur Facebook
    • Partager sur Twitter
      2 janvier 2024 à 14:40:11

      Je crée une liste et je l'associe à la variable A:

      >>> A = [1, 2, 3]
      >>>

      puis, j'assigne ce A à 2 autres variables B et C:

      >>> B = C = A

      Est-ce que j'ai fabriqué 3 listes différentes ou est-ce que j'ai fabriqué 3 chemins A, B, C qui arrivent au même objet liste contenant [1, 2, 3]?

      Il suffit de modifier B[0] et regarder ce que deviennent A et C pour avoir une idée de la réponse:

      >>> B[0] = 'XX'
      >>> A
      ['XX', 2, 3]
      >>> C
      ['XX', 2, 3]
      >>>

      Assigner un objet à une variable ne crée pas de copie de l'objet...

      -
      Edité par mps 2 janvier 2024 à 14:42:25

      • Partager sur Facebook
      • Partager sur Twitter
        2 janvier 2024 à 15:59:32

        Merci! Je comprend mieux. A contrario, si  au lieu d'une liste, tu mets un entier dans deux variables, elles sont indépendantes... 

        A=B=3
        A
        3
        B
        3
        B=4
        A
        3
        A=[0,2,3]
        B=A
        A[0]=9
        A
        [9, 2, 3]
        B
        [9, 2, 3]
        

        Pour contourner le problème, j'ai trouvé:

        >>>R=[5,4,3]

        >>>Z=R+[]
        >>>Z
        >>>[5, 4, 3]
        >>>R[0]=12
        >>>Z
        >>>[5, 4, 3]

        -
        Edité par CyrilLanas 2 janvier 2024 à 16:10:20

        • Partager sur Facebook
        • Partager sur Twitter
          2 janvier 2024 à 16:23:07

          Quand on affecte un tableau à une variable genre t1 = [1,2];  la variable contient une RÉFÉRENCE à l'objet tableau. Et t2=t1  copie cette même référence dans t2.

          Le même tableau est donc accessible via les deux variables. si on modifie t1[0] ça modifie le contenu du tableau donc t2[0].

          EDIT par contre si on modifiait t1 par t1 = [3, 4], t1 ferait référence à ce nouvel objet tableau.

          Et les nombres pourquoi c'est pas pareil ?  Et bien si, c'est pareil. Si on fait a=1, a contient une RÉFÉRENCE à la constante 1. Avec b=a, b se réfère à la même constante. Et après b=2, b se réfère à une AUTRE constante. Ça ne modifie pas la constante 1.

          -
          Edité par michelbillaud 2 janvier 2024 à 18:06:41

          • Partager sur Facebook
          • Partager sur Twitter
            2 janvier 2024 à 16:23:34

            Pour faire ce que vous souhaitez, il suffit de faire une copie de votre liste tableau1 

            class Probleme:
                def __init__(self,tableau1,tableau2):
                    self.tableau1 = tableau1
                    self.tableau1bis = tableau1[:] # copie de tableau1
                    self.tableau2=tableau2
                def __str__(self):
                    print("tableau1 =", self.tableau1)
                    print("tableau1bis =", self.tableau1bis)
                    print("tableau2 =", self.tableau2)
                    return ""
                def completer(self,a):
                    self.tableau1.append(a)
            probleme=Probleme([36,42],[10,12])
            print(probleme)
            probleme.completer(5)
            print(probleme)



            • Partager sur Facebook
            • Partager sur Twitter

            Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
            La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

              2 janvier 2024 à 18:10:30

              CyrilLanas a écrit:

              Merci! Je comprend mieux. A contrario, si  au lieu d'une liste, tu mets un entier dans deux variables, elles sont indépendantes...

              C'est le vocabulaire que vous utilisez qui ne va pas.

              Si j'écris:

              >>> A = B = 20

              le même objet entier avec la valeur 20 a été assigné à A et à B.

              Si j'écris:

              >>> A = B = [1, 2, 3]

              j'ai aussi assigné le même objet à A et à B.

              Là où ça se complique, c'est lorsqu'on cherche à modifier l'objet. On sait modifier une liste mais côté entier on ne sait pas modifier 20 en 21 sans assigner l'objet 21 à A (ou à B).

              Ecrire Z = R + [], c'est assigner à Z une nouvelle liste fabriquée en concaténant R et [].

              Il y a donc 2 concepts: assigner un objet à une variable, (pouvoir) modifier l'objet associé à.

              Pour assigner à Z une copie de R, on pourra écrire: Z = list(R) ou Z = R[:] ou Z = R.copy(). Et on aura un autre problème intéressant lorsque R sera liste de listes (et non plus liste d'entiers).




              • Partager sur Facebook
              • Partager sur Twitter
                2 janvier 2024 à 18:37:52

                Et c'est

                là qu'il faut préciser que A[:] retourne une copie superficielle, un autre tableau mais contenant les mêmes références

                >>> A = [ 1, [2, 3]]
                >>> copie = A[:]
                >>> copie
                [1, [2, 3]]
                >>> A[1][1] = 4
                >>> A
                [1, [2, 4]]
                >>> copie
                [1, [2, 4]]
                >>> 

                Cette œuvre d'art vous est offerte gratuitement pour la nouvelle année

                C'est aussi le cas (shallow copy) de la méthode copy.copy. Pour une copy en profondeur, c'est copy.deepcopy(), comme son nom l'indique, qui copie les objets (les tableaux, les dictionnaires etc)  récursivement. Voir https://docs.python.org/3/library/copy.html

                -
                Edité par michelbillaud 2 janvier 2024 à 18:54:57

                • Partager sur Facebook
                • Partager sur Twitter

                J'essaie de comprendre

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