Python tuple

Résolu
Boto -  
mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   -

Bonjour,

J'ai ce programme en python.

tup1 = 10, 11, 12
print(type(tup1)) 
tup2 = tup1
tup3 = tuple(tup1) 
print(tup1 == tup2) 
print(id(tup1) == id(tup2)) 
print(tup1 is tup2) 
print('-' * 15)
print(tup1 == tup3) 
print(id(tup1) == id(tup3))
print(tup1 is tup3)

Je ne comprends pas pourquoi les deux dernières lignes renvoient True. Pour moi, vu que l'on a utilisé le constructeur de tuple, tup3 a les mêmes valeurs que tup1 mais n'a pas la même référence. Est-ce que quelqu'un pourrait m'expliquer pourquoi cela renvoie True ?

2 réponses

  1. PierrotLeFou
     

    J'ai ajouté les lignes suivantes à ton code:

    print(id(tup1[0]) == id(tup3[0]))
    tup4 = tuple(tup1[:])
    print(id(tup4) == id(tup1))
    tup5 = (10, 11, 12)
    print(tup5 is tup1)

    Un tuple n'étant pas mutable, il prend sans doute l'identité de ses composantes.

    Petit test en invite:

    >>> l = [1, 2, 3]
    >>> m = l
    >>> id(l) == id(m)
    True
    >>> m = l[:]
    >>> id(m) == id(l)
    False

    Les listes sont mutables.

    1
    1. Boto
       

      D'accord ça vient de là, merci beaucoup pour votre réponse.

      0
  2. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
     

    Bonjour,

    Apparemment c'est plus subtil, et le résultat dépend de si on est dans l'interpréteur python (REPL) ou si on exécute un script python. Prenons cet extrait de code :

    tup1 = (10, 11, 12)
    tup2 = tup1
    tup3 = tuple(tup1)
    tup4 = (10, 11, 12)
    print(tup1, id(tup1))
    print(tup2, id(tup2))
    print(tup3, id(tup3))
    print(tup4, id(tup4))

    Si je mets ce code dans un script que j'exécute, j'obtiens :

    (mando@silk) (~) $ python3 toto.py
    (10, 11, 12) 140590417604288
    (10, 11, 12) 140590417604288
    (10, 11, 12) 140590417604288
    (10, 11, 12) 140590417604288

    Si par contre je suis dans le REPL :

    (mando@silk) (~) $ python3
    Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> tup1 = (10, 11, 12)
    >>> tup2 = tup1
    >>> tup3 = tuple(tup1)
    >>> tup4 = (10, 11, 12)
    >>> print(tup1, id(tup1))
    (10, 11, 12) 139713892358464
    >>> print(tup2, id(tup2))
    (10, 11, 12) 139713892358464
    >>> print(tup3, id(tup3))
    (10, 11, 12) 139713892358464
    >>> print(tup4, id(tup4))
    (10, 11, 12) 139713889771392

    On voit qu’étonnement, tup4 n'a pas le même identifiant. Pourquoi ? Mystère. Mais du coup ça veut dire que "is" fera la distinction entre tup4 et les autres. On peut du coup se demander pourquoi tup3 n'est pas dans le même cas...

    Si tuple était un "vrai" immutable (comme les chaînes de caractères ou les booléens) on devrait avoir toujours le même identifiant si les valeurs des deux variables comparées coïncident, et on pourrait utiliser l'opérateur is (qui compare les identifiants) sans problème :

    >>> s1 = "abc"
    >>> s2 = "abc"
    >>> id(s1)
    9942560
    >>> id(s2)
    9942560

    J'observe le même comportement étrange sur les tuples avec ipython3 (ce qui pour le coup ne m'étonne pas si on part du principe qu'ipython3 n'est qu'une surcouche à python3).

    Bref, pour comparer deux tuples, j'aurais tendance à utiliser systématiquement l'opérateur ==, car le comportement de l'opérateur is semble dépendre du contexte...

    Bonne chance

    1
    1. filou
       

      Salut.

      Pour ma part le comportement de is est tellement peu logique (presque un comportement indéterminé) que je fais comme tout le monde, je ne l'utilise que pour l'idendité de None...

      >>> True is bool
      False
      >>> True is bool()
      False
      >>> False is bool
      False
      >>> False is bool()
      True
      
      
      0
      1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944 > filou
         

        Le comportement de is est bien défini : il compare juste l'identifiant des deux objets mis en jeu dans le test.

        • Pour les types immutables (bool, str, ...), is peut donc remplacer un test d'égalité. Les nouveaux linter python incitent d'ailleurs à comparer un booléan avec True ou False via is.
        • Pour les autres types, il ne faut utiliser is que si l'on souhaite vérifier qu'une instance d'un objet est bien une instance particulière. L'exemple ci-dessous illustre la nuance entre is et == :
          In [1]: l1 = [1, 2, 3]
          
          In [2]: l2 = [1, 2, 3]
          
          In [3]: l3 = l1
          
          In [4]: l1 == l2
          Out[4]: True
          
          In [5]: l2 == l3
          Out[5]: True
          
          In [6]: l1 == l3
          Out[6]: True
          
          In [7]: l1 is l2
          Out[7]: False
          
          In [8]: l1 is l3
          Out[8]: True
          
          In [9]: l3 is l1
          Out[9]: True

        Bonne chance

        0