Comparez si deux variables référencent le même objet en python

Réponses:

133

C'est à cela que issert: x is yrenvoie Truesi xet ysont le même objet.

Jochen Ritzel
la source
6
Dans l'exemple, x is zrenvoie False. Mais si x et z reçoivent les mêmes valeurs au lieu de listes (par exemple x, z = 13, 13), alors x is zretourne True. Pourquoi donc?
Projet de loi
12
@Bill: C'est un artefact de la façon dont python gère les ints. Python alloue des objets entiers vers lesquels xet zpointent. Étant donné que les petits entiers sont communs à l'échec (-1 comme valeur d'erreur, 0 chaque fois que vous indexez quelque chose, les petits nombres sont généralement des valeurs par défaut raisonnables) Python optimise en préallouant de petits nombres (-5 à 256) et réutilise le même objet entier. Ainsi, votre exemple ne fonctionne que pour les nombres de cette plage. Essayez d'attribuer quelque chose de plus grand, c'est-à-dire 270. Pour plus d'informations, regardez ici
ted
1
@AndresR Non, c'est faux. isvérifie si deux noms font référence au même emplacement mémoire. Cela n'a rien à voir avec l'objet lui-même. Il est facile d'avoir des objets immuables comme des chaînes qui sont égales mais qui ne sont pas stockées au même emplacement, par exemple ''a'*10000 is 'a' * 10000est False.
Jochen Ritzel
1
@JochenRitzel Vous avez tout à fait raison, merci pour ce commentaire! Alors, je ne comprends pas ce qui se passe "af" is "af"ou () is ()... pourquoi partagent-ils le même emplacement mémoire?
AndresR
2
@AndreasR Pour les chaînes / nombres littéraux dans le code, le compilateur vérifie qu'elles n'existent qu'une seule fois et les réutilise. Des valeurs spéciales telles que (), None, True, False, etc. sont également définies comme des singletons. Pendant l'exécution, le runtime essaie également de réutiliser de petits nombres et chaînes, mais à la fin, c'est un compromis entre la vitesse et la mémoire et ce qui se passe dépend de la façon dont le runtime Python a été implémenté.
Jochen Ritzel
12

y is xsera True, y is zsera False.

Mark Rushakoff
la source
11

Alors que les deux solutions correctes x is zet id(x) == id(z)ont déjà été publiées, je tiens à souligner un détail de mise en œuvre de python. Python stocke les entiers en tant qu'objets, en tant qu'optimisation, il génère un tas de petits entiers à son début (-5 à 256) et pointe CHAQUE variable contenant un entier avec une petite valeur vers ces objets pré-initialisés. Plus d'informations

Cela signifie que pour les objets entiers initialisés aux mêmes petits nombres (-5 à 256), vérifier si deux objets sont identiques retournera true ( ON C-Pyhon , pour autant que je sache, il s'agit d'un détail d'implémentation ), tandis que pour plus nombres cela ne renvoie vrai que si un objet est initialisé par l'autre.

> i = 13
> j = 13
> i is j
True

> a = 280
> b = 280
> a is b
False

> a = b
> a
280
> a is b
True
ted
la source
python3.6: a = 98765; b = 98765; a est b => Vrai. Quelque chose a changé apparemment.
Mikhail Kalashnikov
@MikhailKalashnikov Non. J'ai testé sur Python 3.6.2, cela existe toujours.
nix
existe toujours python 3.7.7
Bill Huang
9

Vous pouvez également utiliser id () pour vérifier à quel objet unique se réfère chaque nom de variable.

In [1]: x1, x2 = 'foo', 'foo'

In [2]: x1 == x2
Out[2]: True

In [3]: id(x1), id(x2)
Out[3]: (4509849040, 4509849040)

In [4]: x2 = 'foobar'[0:3]

In [5]: x2
Out[5]: 'foo'

In [6]: x1 == x2
Out[6]: True

In [7]: x1 is x2
Out[7]: False

In [8]: id(x1), id(x2)
Out[8]: (4509849040, 4526514944)
Facture
la source
La note de @ ted sur l'utilisation de id est tout à fait pertinente ici.
Leo Ufimtsev
2

J'aime vraiment avoir un retour visuel, c'est pourquoi j'ouvre parfois simplement http://www.pythontutor.com/visualize.html#mode=edit pour voir comment la mémoire est allouée et ce qui fait référence à quoi.

entrez la description de l'image ici

Ajout de ce gif génial car cette réponse concerne la visualisation.

user1767754
la source
2

Ceci est de docs.python.org: "Chaque objet a une identité, un type et une valeur. L'identité d'un objet ne change jamais une fois qu'il a été créé; vous pouvez le considérer comme l'adresse de l'objet en mémoire. L'opérateur 'est' compare l'identité de deux objets; la fonction id () renvoie un entier représentant son identité. "

Apparemment, chaque fois que vous modifiez la valeur, l'objet est recréé comme indiqué par le changement d'identité. La ligne x = 3 suivie de la ligne x = 3,14 ne donne aucune erreur et donne différentes identités, types et valeurs pour x.

Scott Woods
la source
1
Excellente prise de doc.
prosti