web-dev-qa-db-fra.com

Comprendre l'opérateur "est" de Python

L'opérateur is ne correspond pas aux valeurs des variables, mais aux instances elles-mêmes.

Qu'est-ce que cela signifie vraiment?

J'ai déclaré deux variables nommées x et y en affectant les mêmes valeurs dans les deux variables, mais renvoie False lorsque j'utilise l'opérateur is.

J'ai besoin d'une clarification. Voici mon code.

x = [1, 2, 3]
y = [1, 2, 3]

print x is y #It prints false!
96
Anisuzzaman Khan

Vous avez mal compris ce que l’opérateur is teste. Il vérifie si deux variables pointent le même objet , et non si deux variables ont la même valeur.

De la documentation pour l'opérateur is :

Les opérateurs is et is not Testent l'identité de l'objet: x is y Est vraie si et seulement si x et y sont le même objet.

Utilisez l'opérateur == À la place:

print x == y

Ceci affiche True. x et y sont deux listes distinctes :

x[0] = 4
print(y)  # prints [1, 2, 3]
print(x == y)   # prints False

Si vous utilisez la fonction id() _ , vous verrez que x et y ont des identifiants différents:

>>> id(x)
4401064560
>>> id(y)
4401098192

mais si vous deviez assigner y à x, les deux pointeraient sur le même objet:

>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True

et is montre que les deux sont le même objet, il retourne True.

Rappelez-vous qu'en Python, les noms ne sont que des étiquettes faisant référence à des valeurs ; vous pouvez avoir plusieurs noms pointés sur le même objet. is vous indique si deux noms pointent vers le même objet. == Vous indique si deux noms font référence à des objets ayant la même valeur.

161
Martijn Pieters

n autre doublon demandait pourquoi deux chaînes égales ne sont généralement pas identiques, ce à quoi on ne répond pas vraiment ici:

>>> x = 'a' 
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False

Alors, pourquoi ne sont-ils pas la même chaîne? Surtout compte tenu de ceci:

>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True

Remettons la deuxième partie pour un peu. Comment le premier pourrait-il être vrai?

L'interprète doit avoir une "table d'internement", une table mappant les valeurs de chaîne sur des objets chaîne. Ainsi, chaque fois que vous essayez de créer une nouvelle chaîne avec le contenu 'abc', vous récupérez le même objet. Wikipedia a une discussion plus détaillée sur le fonctionnement de l'internat.

Et Python a une table d'internement de chaînes; vous pouvez interner manuellement des chaînes avec le sys.intern méthode.

En fait, Python est autorisé à interner automatiquement tous les types immuables, mais pas requis : différentes implémentations interneront différentes valeurs.

CPython (l'implémentation que vous utilisez si vous ne savez pas quelle implémentation vous utilisez) auto-interne de petits entiers et des singletons spéciaux comme False, mais pas de chaînes (ou de grands entiers ou de petits n-uplets), ou autre chose). Vous pouvez voir cela assez facilement:

>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False

OK, mais pourquoi z et w étaient-ils identiques?

Ce n'est pas l'interprète qui entre automatiquement en interne, ce sont les valeurs de pliage du compilateur.

Si la même chaîne de compilation apparaît deux fois dans le même module (il est difficile de définir exactement ce que cela signifie. Ce n'est pas la même chose qu'un littéral de chaîne, car r'abc', 'abc', et 'a' 'b' 'c' sont tous des littéraux différents mais la même chaîne (mais facile à comprendre intuitivement), le compilateur ne créera qu'une instance de la chaîne, avec deux références.

En fait, le compilateur peut aller encore plus loin: 'ab' + 'c' peut être converti en 'abc' par l'optimiseur, auquel cas il peut être plié avec un 'abc' constante dans le même module.

Encore une fois, c’est quelque chose Python est autorisé mais pas obligatoire. Mais dans ce cas, CPython plie toujours les petites chaînes (et également, par exemple, les petits n-uplets). (Bien que la déclaration de l’interprète interactif- Le compilateur by-statement n'exécute pas la même optimisation que le compilateur module à la fois, vous ne verrez donc pas exactement les mêmes résultats de manière interactive.)


Alors, que devriez-vous faire à ce sujet en tant que programmeur?

Eh bien… rien. Vous n'avez presque jamais de raison de vous en soucier si deux valeurs immuables sont identiques. Si vous voulez savoir quand vous pouvez utiliser a is b au lieu de a == b, vous posez la mauvaise question. Toujours utiliser a == b sauf dans deux cas:

  • Pour des comparaisons plus lisibles avec les valeurs singleton telles que x is None.
  • Pour les valeurs mutables, lorsque vous devez savoir si la mutation de x affectera le y.
52
abarnert

Invitée par un question dupliquée , cette analogie pourrait fonctionner:

# - Darling, I want some pudding!
# - There is some in the fridge.

pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True

# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.

pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False
7
Amadan

is ne renvoie true que s'il s'agit du même objet. S'ils étaient identiques, un changement de l'un apparaîtrait également dans l'autre. Voici un exemple de la différence.

>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]
7
Mark Ransom

is et is not sont les deux opérateurs d’identité en Python. is L'opérateur ne compare pas les valeurs des variables, mais compare les identités des variables. Considère ceci:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> hex(id(a))
'0x1079b1440'
>>> hex(id(b))
'0x107960878'
>>> a is b
False
>>> a == b
True
>>>

L'exemple ci-dessus vous montre que l'identité (peut également être l'adresse mémoire de Cpython) est différente pour a et b (même si leurs valeurs sont identiques). C'est pourquoi quand vous dites a is b il retourne la valeur false en raison de la discordance dans les identités des deux opérandes. Cependant, quand vous dites a == b, il retourne vrai car le == l'opération ne vérifie que si les deux opérandes ont la même valeur.

Exemple intéressant (pour le grade supplémentaire):

>>> del a
>>> del b
>>> a = 132
>>> b = 132
>>> hex(id(a))
'0x7faa2b609738'
>>> hex(id(b))
'0x7faa2b609738'
>>> a is b
True
>>> a == b
True
>>>

Dans l'exemple ci-dessus, même si a et b sont deux variables différentes, a is b a retourné True. En effet, le type de a est int, un objet immuable. Donc python (je suppose pour économiser de la mémoire) a alloué le même objet à b lorsqu’il a été créé avec la même valeur. Ainsi, dans ce cas, les identités des variables correspondantes et a is b s'est avéré être True.

Ceci s'appliquera à tous les objets immuables:

>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>

J'espère que ça t'as aidé.

5
gixxer

Comme vous pouvez le vérifier ici pour un petit nombre entier. Les nombres supérieurs à 257 ne sont pas un petit ints, ils sont donc calculés comme un objet différent.

Il vaut mieux utiliser == à la place dans ce cas.

Pour plus d'informations, cliquez ici: http://docs.python.org/2/c-api/int.html

3
CS Gamer

x is y Est identique à id(x) == id(y), en comparant l'identité des objets.

Comme @ tomasz-kurgan l’a souligné dans le commentaire ci-dessous, l’opérateur is se comporte de manière inhabituelle avec certains objets.

Par exemple.

>>> class A(object):
...   def foo(self):
...     pass
... 
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True

Réf;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24

3
Nizam Mohamed

X pointe vers un tableau, Y pointe vers un tableau différent. Ces tableaux sont identiques, mais l'opérateur is examinera ces pointeurs, qui ne sont pas identiques.

2
Neko

Il compare l'identité de l'objet, c'est-à-dire si les variables font référence au même objet en mémoire. C'est comme le == in Java ou C (lors de la comparaison de pointeurs).

1
mipadi

Un exemple simple avec des fruits

fruitlist = [" Apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )

Sortie:

True
False
False

Si tu essayes

fruitlist = [" Apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )

La sortie est différente:

True
True
True

En effet, l'opérateur == compare uniquement le contenu de la variable. Pour comparer les identités de 2 variables, utilisez l'opérateur is

Pour imprimer le numéro d'identification:

print ( id( variable ) )
1
ForsakenOne