Deux variables en Python ont la même id
:
a = 10
b = 10
a is b
>>> True
Si je prends deux list
s:
a = [1, 2, 3]
b = [1, 2, 3]
a is b
>>> False
selon ce lien Senderle a répondu que les références d'objets immuables ont le même identifiant et que les objets mutables comme les listes ont des identifiants différents.
Alors maintenant, selon sa réponse, les tuples devraient avoir les mêmes identifiants - ce qui signifie:
a = (1, 2, 3)
b = (1, 2, 3)
a is b
>>> False
Idéalement, comme les n-uplets ne sont pas mutables, il devrait retourner True
, mais il retourne False
!
Quelle est l'explication?
Les objets immuables n'ont pas la même id
et, en réalité, ceci n'est pas vrai pour tout type d'objets que vous définissez séparément. En règle générale, chaque fois que vous définissez un objet en Python, vous créez un nouvel objet avec une nouvelle identité.
Cependant, dans un souci d’optimisation (la plupart du temps), il existe quelques exceptions pour les petits entiers (entre -5 et 256) et les petites chaînes (chaînes internes, avec une longueur spéciale (généralement moins de 20 caractères)) qui sont singletons et ont la même id
(en fait, un objet avec plusieurs pointeurs). Vous pouvez vérifier ce fait comme suit:
>>> 30 is 20 + 10
True
>>>
>>> 300 is 200 + 100
False
>>> 'aa' * 2 is 'a' * 4
True
>>> 'aa' * 20 is 'a' * 40
False
Et pour un objet personnalisé:
>>> class A:
... pass
...
>>> A() is A() # Every time you create an instance you'll have a new instance with new identity
False
Notez également que l'opérateur is
vérifiera l'identité de l'objet et non sa valeur. Si vous voulez vérifier la valeur, vous devez utiliser ==
:
>>> 300 == 3*100
True
Et comme il n’existe pas de règle de ce type pour les n-uplets (autres types), si vous définissez les deux mêmes n-uplets quelle que soit leur taille, ils obtiendront leurs propres identifiants:
>>> a = (1,)
>>> b = (1,)
>>>
>>> a is b
False
Et notez que le fait de singleton entiers et de chaînes interned est vrai même lorsque vous les définissez dans des objets mutables et immuables:
>>> a = (100, 700, 400)
>>>
>>> b = (100, 700, 400)
>>>
>>> a[0] is b[0]
True
>>> a[1] is b[1]
False
Immuable !=
même objet.*
Un objet immuable est simplement un objet dont l'état ne peut pas être modifié; et c'est tout. Lorsqu'un nouvel objet est créé, une nouvelle adresse lui sera attribuée. Ainsi, vérifier si les adresses sont égales avec is
retournera False
.
Le fait que 1 is 1
ou "a" is "a"
renvoie True
est dû à la mise en cache des entiers et à la chaîne interning effectuée par Python, ne la laissez pas vous dérouter; il n'est pas lié aux objets en question étant mutables/immuables.
* Les objets immuables vides font référence au même objet et leur is
ness renvoie true, il s'agit toutefois d'un cas spécifique à l'implémentation.
Jetez un oeil à ce code:
>>> a = (1, 2, 3)
>>> b = (1, 2, 3)
>>> c = a
>>> id(a)
178153080L
>>> id(b)
178098040L
>>> id(c)
178153080L
Afin de comprendre pourquoi a is c
est évalué en tant que True
alors que a is b
donne False
, je vous recommande vivement d'exécuter l'extrait étape par étape ci-dessus dans Python Online Tutor . La représentation graphique des objets en mémoire vous permettra de mieux comprendre ce problème (je joins une capture d'écran).
Vérifiez ci-dessous le code .. Tupils a et b conservent leurs anciennes références (ID) lorsque nous avons affecté leurs anciennes valeurs. (MAIS CELA NE SERAIT PAS LE CAS DES LISTES COMME ILS SONT MUTABLES)
Initialement, a et b ont les mêmes valeurs ((1,2)), mais ils ont des ID de différence. Après modification de leurs valeurs, lorsque nous réaffectons la valeur (1,2) à a et b, ils se réfèrent maintenant à LEUR PROPRE identificateurs identiques (88264264 et 88283400 respectivement).
>>> a = (1,2)
>>> b = (1,2)
>>> a , b
((1, 2), (1, 2))
>>> id(a)
88264264
>>> id(b)
88283400
>>> a = (3,4)
>>> b = (3,4)
>>> id(a)
88280008
>>> id(b)
88264328
>>> a = (1,2)
>>> b = (1,2)
>>> id(a)
88264264
>>> id(b)
88283400
>>> a , b
((1, 2), (1, 2))
>>> id(a) , id(b)
(88264264, 88283400)
>>>
** Vérifiez le lien Pourquoi les n-uplets n'ont-ils pas le même identifiant si on leur attribue les mêmes valeurs? aussi après avoir lu ceci. Un autre cas a également été discuté ici.