Pourquoi la comparaison de chaînes en utilisant soit "= = " ou " est " parfois produire un résultat différent?
J'ai un programme en Python où les deux variables sont définies à la valeur 'public'
. Dans une expression conditionnelle, j'ai la comparaison var1 is var2
qui échoue, mais si je le change pour var1 == var2
il retourne True
.
Maintenant, si j'ouvre mon interpréteur Python et faire la même chose "est" de la comparaison, il réussit.
>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True
Ce qui me manque ici?
- Je ne sais rien à propos de Python, mais est-il possible que l'un est la comparaison des valeurs tandis que l'autre est comparer des objets?
- voir: stackoverflow.com/questions/1392433/...
- Ce problème se produit également lorsque vous lisez une console d'entrée, par exemple:
input = raw_input("Decide (y/n): ")
. Dans ce cas, une entrée de "y" etif input == 'y':
retourne "True", alors queif input is 'y':
retournera False. - Ce blog fournit une mesure plus complète de l'explication que n'importe quelle réponse guilload.com/python-string-interning
- Comme @chris-rico mentionne, j'ai une grande explication ici stackoverflow.com/q/15541404/1695680
- pouvez-vous expliquer plus précisément pourquoi dans l'affiche originale exemple, le "est" de l'opérateur échouer sur le script, mais le même opérateur sur les mêmes chaînes de retourner "true" sur le mode interactif? C'est le même interprète, alors nous devrions attendre le même comportement sur un stage que vous avez l'exécution d'un script ou d'exécuter en mode interactif, à droite?
- Double Possible de Est-il une différence entre `==` et `est` en Python?
Vous devez vous connecter pour publier un commentaire.
is
est une analyse d'identité,==
est l'égalité des tests. ce qui se passe dans votre code devrait être imité par l'interprète comme ceci:donc, pas étonnant qu'ils ne sont pas les mêmes, non?
En d'autres termes:
is
est leid(a) == id(b)
==
vs.equals()
en Java. La meilleure partie est que le Python==
n'est pas analogue à la Java==
.None
valeur?None
valeur. Donc, il a toujours le même id.is None
expression. Lire à ce sujet hier, après avoir indiqué que ci-dessus.a = 'pub'; b = ''.join(a); a == b, a is b
==
lorsque l'on compare immuable types (comme ints) etis
lorsque l'on compare les objets." Vous avez presque jamais vous voulezis
pour comparer des objets définis par l'utilisateur. La bonne règle de base est "l'Utilisation==
pour tout, maisNone
etNotImplemented
comparaisons jusqu'à ce que vous comprenez ce que vous faites." L'article omet aussi de transmettre l'identité sémantique deint
s sont Disponible détail d'implémentation qui s'applique uniquement aux petits deint
s, et non comme un mécanisme de mise en cache commun à tous lesint
s.D'autres réponses ici sont correctes:
is
est utilisé pour identité comparaison, alors que==
est utilisé pour l'égalité comparaison. Depuis que vous vous souciez de l'égalité (les deux chaînes doivent contenir les mêmes personnages), dans ce cas, leis
opérateur est tout simplement faux et vous devriez être en utilisant==
à la place.La raison
is
fonctionne de manière interactive, c'est que la plupart des littéraux de chaîne sont interné par défaut. De Wikipedia:Alors, quand vous avez deux littéraux de chaîne (les mots qui sont littéralement tapé dans votre code source du logiciel, entouré par des guillemets) dans votre programme qui ont la même valeur, le Python, le compilateur va automatiquement stagiaire les chaînes, les rendant à la fois stocké dans le même emplacement mémoire. (Notez que ce n'est pas toujours se produire, et les règles d'lorsque cela se produit sont assez compliquées, donc merci de ne pas compter sur ce problème dans le code de production!)
Depuis votre session interactive les deux chaînes sont en fait stockées dans le même emplacement de mémoire, ils ont la même identité, de sorte que le
is
opérateur fonctionne comme prévu. Mais si vous construisez une chaîne de caractères par une autre méthode (même si cette chaîne contient exactement les mêmes caractères), puis la chaîne peut être l'égalité des, mais il n'est pas la même chaîne -- qui est, il a un autre identité, car il est stocké dans un endroit différent dans la mémoire.==
/!=
lorsque les chaînes sont créées par le biais de différentes méthodes?==
etis
en fonction du type de contrôle que vous voulez. Si vous vous souciez de la les chaînes égal (qui est, ayant le même contenu), alors vous devriez toujours utiliser==
. Si vous vous souciez de savoir si les deux Python noms font référence à la même instance d'objet, vous devez utiliseris
. Vous pourriez avoir besoinis
si vous écrivez du code qui gère les différents lots de valeurs sans se soucier de leur contenu, ou bien si vous savez qu'il y est un seul de quelque chose et que vous voulez ignorer les autres objets prétendant être de cette chose. Si vous n'êtes pas sûr, toujours choisi==
.==
vérifie d'abord l'identité de l'objet, puis, à défaut, par la chaîne de l'égalité?La
is
mot-clé est un test pour l'identité de l'objet tout en==
est une comparaison de la valeur.Si vous utilisez
is
, le résultat sera vrai si et seulement si l'objet est le même objet. Cependant,==
sera vrai de tout temps les valeurs de l'objet sont les mêmes.Une dernière chose à noter, vous pouvez utiliser le stagiaire en fonction afin de s'assurer que vous obtenez une référence à la même chaîne:
Comme l'a souligné ci-dessus, vous ne devriez probablement pas être en train de faire est de déterminer l'égalité sur les cordes. Mais cela peut être utile de savoir si vous avez une sorte de bizarre obligation d'utiliser
is
.Noter que le stagiaire de la fonction s'est déplacé d'une fonction intégrée pour être dans le module
sys
pour Python 3.is
est une analyse d'identité,==
est l'égalité des tests. Ce que cela signifie, c'est queis
est une manière de vérifier si deux choses sont les même choses, ou tout simplement l'équivalent.Dire que vous avez une simple
person
objet. S'il est nommé 'Jack' et il est '23' ans, il est équivalent à un autre 23yr le vieux Jack, mais ce n'est pas la même personne.Ils sont du même âge, mais ils ne sont pas à la même instance de la personne. Une chaîne peut être équivalent à un autre, mais ce n'est pas le même objet.
C'est une note de côté, mais dans idiomatiques python, vous verrez souvent des choses comme:
C'est sûr, parce que il est garanti d'être une instance de l'Objet Nul (c'est à dire, Aucun).
Si vous n'êtes pas sûr de ce que vous êtes en train de faire, utilisez le '=='.
Si vous avez un peu plus de connaissances à ce sujet vous pouvez utiliser 'est' pour les objets connus comme "Aucun".
Sinon vous allez finir par me demander pourquoi les choses ne fonctionnent pas et pourquoi cela se produit:
Je ne suis même pas sûr si certaines choses sont garantis de rester le même entre les différentes versions de python/implémentations.
À partir de mon expérience limitée avec python,
is
est utilisé pour comparer deux objets pour voir si elles sont le même objet, par opposition à deux objets différents avec la même valeur.==
est utilisé pour déterminer si les valeurs sont identiques.Ici est un bon exemple:
s1
est une chaîne unicode, ets2
est normal chaîne. Ils ne sont pas du même type, mais sont de la même valeur.Je pense que cela a à voir avec le fait que, lorsque le " est " de comparaison de la valeur false, deux objets distincts sont utilisés. Si elle est true, ce qui signifie en interne, il utilise exactement le même objet et non pas d'en créer un nouveau, peut-être parce que vous les avez créées à l'intérieur d'une fraction de 2 secondes et parce qu'il n'y a pas un grand écart de temps entre les deux il est optimisé et utilise le même objet.
C'est pourquoi vous devez utiliser l'opérateur d'égalité
==
, pasis
, pour comparer la valeur d'un objet de type string.Dans cet exemple, j'ai fait s2, ce qui est un autre objet de type string précédemment égal à "un", mais il n'est pas le même objet que
s
, parce que l'interprète n'a pas utilisé le même objet que je n'ai pas d'abord de l'attribuer à "un", si j'avais ça aurait fait le même objet..replace()
comme un exemple dans ce contexte est sans doute pas la meilleure, mais, parce que sa sémantique peut être source de confusion.s2 = s2.replace()
sera toujours créer un nouvelles chaîne de caractères de l'objet, de l'attribution de la nouvelle chaîne de l'objet às2
, et puis les disposer de l'objet string quis2
utilisé pour le pointage. Donc, même si vous n'avezs = s.replace('one', 'one')
vous obtenez toujours un nouvel objet de type string.Je crois que ce qui est connu comme "internement" les chaînes. Python fait cela, donc ne Java, et ainsi de faire le C et le C++ lors de la compilation dans optimisé modes.
Si vous utilisez deux des chaînes identiques, au lieu de gaspiller de la mémoire par la création de deux objets string, tous les internés des chaînes de caractères avec le même contenu, point à la même mémoire.
Cette résultats dans le Python "est" de l'opérateur renvoie True parce que deux chaînes avec le même contenu sont pointent vers le même objet de type string. Cela arrivera aussi en Java et en C.
Ce n'est utile que pour les économies de mémoire si. Vous ne pouvez pas compter sur elle pour tester la chaîne de l'égalité, parce que les différents interpréteurs et compilateurs et JIT moteurs ne peuvent pas toujours le faire.
Je réponds à la question, même si la question est ancienne, car aucune des réponses ci-dessus citations de la langue de référence
En fait l'opérateur vérifie l'identité et l'opérateur == vérifie l'égalité,
De Référence Du Langage:
Types affecte presque tous les aspects du comportement des objets. Même l'importance de l'identité de l'objet est affecté dans un certain sens: pour immuable types, opérations que calculer de nouvelles valeurs peuvent renvoyer en fait une référence à un objet existant avec le même type et de même valeur, alors que pour les objets mutables ce n'est pas autorisé. E. g., après a = 1; b = 1, a et b peuvent ou ne peuvent pas se référer au même objet avec la valeur, en fonction de la mise en œuvre, mais après c = []; d = [], c et d sont garantis pour faire référence à deux différents, uniques, nouvellement créé vide listes. (A noter que c = d = [] attribue le même objet à la fois c et d.)
donc, à partir de ci-dessus énoncé, nous pouvons en déduire que les chaînes qui est immuable type peut échouer lorsque cette option est cochée avec "est" et peut vérifié réussir lorsque cette option est cochée avec "est"
La même chose s'applique pour les int,tuple, qui sont aussi immuables types
La
==
opérateur de test de la valeur d'équivalence. Leis
, l'opérateur vérifie l'identité de l'objet, Python teste si les deux sont vraiment le même objet(c'est à dire, vivre à la même adresse en mémoire).Dans cet exemple, Python seulement créé un objet de type string, et les deux
a
etb
se réfère à elle. La raison en est que Python en interne, les caches et les réutilise certaines chaînes comme de l'optimisation, il est vraiment juste une chaîne de caractères "banane" dans la mémoire, partagé par a et b; Pour déclencher le comportement normal, vous avez besoin d'utiliser plus de chaînes:Lorsque vous créez deux listes, vous obtenez deux objets:
Dans ce cas, nous disons que les deux listes sont équivalents, car ils ont les mêmes éléments, mais pas identiques, car ils ne sont pas le même objet. Si deux objets sont identiques, ils sont aussi équivalents, mais s'ils sont équivalents, ils ne sont pas nécessairement identiques.
Si
a
se réfère à un objet et vous attribuerb = a
, alors les deux variables font référence au même objet:is
est une analyse d'identité,==
est l'égalité des tests (voir La Documentation Python).Dans la plupart des cas, si
a is b
, puisa == b
. Mais il y a des exceptions, par exemple:Donc, vous ne pouvez utiliser
is
pour les tests d'identité, jamais tests d'égalité.is
permettra de comparer l'emplacement de la mémoire. Il est utilisé pour le niveau de l'objet de la comparaison.==
permettra de comparer les variables dans le programme. Il est utilisé pour la vérification à la valeur de niveau.is
vérifie l'adresse de niveau d'équivalence==
vérifie la valeur d'équivalence de niveau de