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!
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
etis not
Testent l'identité de l'objet:x is y
Est vraie si et seulement six
ety
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.
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:
x is None
.x
affectera le y
.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
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]
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é.
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
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
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.
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).
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 ) )