Mon Google-fu m'a échoué.
En Python, les deux tests d'égalité suivants sont-ils équivalents?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
Est-ce vrai pour les objets où vous compareriez des instances (un list
mot à dire)?
D'accord, donc ce genre de réponses à ma question:
L = []
L.append(1)
if L == [1]:
print 'Yay!'
# Holds true, but...
if L is [1]:
print 'Yay!'
# Doesn't.
Donc, les ==
tests is
valent où les tests pour voir s'ils sont le même objet?
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
sortie:False True False
.b = a[:]
partie de copie de la liste des opérateurs de tranche, j'ai donc modifié votre réponse pour y ajouter un commentaire. On dirait que je viens d'atteindre le seuil pour ne pas avoir à faire réviser mes modifications avant de les appliquer, alors j'espère que c'est cool avec vous. Quoi qu'il en soit, voici une référence utile pour copier des listes que j'ai rencontrées et que j'ai dû faire référence pour comprendre ce que vous faisiez: stackoverflow.com/a/2612815/4561887==
. Ainsi,5.0
par exemple, est une valeur à virgule flottante, tandis que5
est un entier. Mais5.0 == 5
reviendra toujoursTrue
car ils représentent la même valeur. En termes de performances et de typage de canard,is
est toujours testé par l'interprète en comparant les adresses mémoire de l'opérande, tandis que==
c'est à l'objet de décider s'il se définit comme égal à autre chose.1000 is 10**3
correspond à True dans Python 3.7 puisque 10 ** 3 est de typeint
. Mais donne la valeur1000 is 1e3
False puisque 1e3 est de typefloat
.1000 is 10**3
dépend de l'implémentation et dépend de la pré-évaluation par le compilateur de l'expression10**3
.x=10; 1000 is x**3
évalue àFalse
.Il existe une règle simple pour vous dire quand utiliser
==
ouis
.==
est pour l' égalité des valeurs . Utilisez-le lorsque vous souhaitez savoir si deux objets ont la même valeur.is
est pour l' égalité de référence . Utilisez-le lorsque vous souhaitez savoir si deux références font référence au même objet.En général, lorsque vous comparez quelque chose à un type simple, vous vérifiez généralement l' égalité des valeurs , vous devez donc l'utiliser
==
. Par exemple, l'intention de votre exemple est probablement de vérifier si x a une valeur égale à 2 (==
), et non pas s'ilx
fait littéralement référence au même objet que 2.Autre chose à noter: en raison du fonctionnement de l'implémentation de référence CPython, vous obtiendrez des résultats inattendus et incohérents si vous utilisez par erreur
is
pour comparer l'égalité de référence sur des entiers:C'est à peu près ce à quoi nous nous attendions:
a
etb
ont la même valeur, mais ce sont des entités distinctes. Mais qu'en est-il?Cela est incompatible avec le résultat précédent. Que se passe t-il ici? Il s'avère que l'implémentation de référence de Python met en cache des objets entiers dans la plage -5..256 en tant qu'instances singleton pour des raisons de performances. Voici un exemple qui le démontre:
C'est une autre raison évidente de ne pas utiliser
is
: le comportement est laissé aux implémentations lorsque vous l'utilisez par erreur pour l'égalité des valeurs.la source
a=500
etb=500
, je voulais juste souligner que si vous définisseza
etb
sur un entier entre [-5, 256],a is b
retourne en faitTrue
. Plus d'informations ici: stackoverflow.com/q/306313/7571052==
détermine si les valeurs sont égales, tandis queis
détermine si elles sont exactement le même objet.la source
Oui, ils ont une différence très importante.
==
: vérifier l'égalité - la sémantique est que les objets équivalents (qui ne sont pas nécessairement le même objet) seront testés comme égaux. Comme le dit la documentation :is
: vérifier l'identité - la sémantique est que l'objet (tel qu'il est conservé en mémoire) est l'objet. Encore une fois, la documentation dit :Ainsi, la vérification d'identité est identique à la vérification de l'égalité des ID des objets. C'est,
est le même que:
où
id
est la fonction intégrée qui renvoie un entier qui "est garanti unique parmi les objets existants simultanément" (voirhelp(id)
) et oùa
etb
tout objet arbitraire.Autres instructions d'utilisation
Vous devez utiliser ces comparaisons pour leur sémantique. Utilisez
is
pour vérifier l'identité et==
pour vérifier l'égalité.Donc, en général, nous utilisons
is
pour vérifier l'identité. Ceci est généralement utile lorsque nous recherchons un objet qui ne devrait exister qu'une seule fois en mémoire, appelé "singleton" dans la documentation.Les cas d'utilisation
is
incluent:None
Les cas d'utilisation habituels
==
incluent:Le cas d'usage général, encore une fois, car
==
, est l'objet que vous voulez peut - être pas le même objet, au lieu , il peut être un équivalent d' unPEP 8 directions
PEP 8, le guide de style Python officiel pour la bibliothèque standard mentionne également deux cas d'utilisation pour
is
:Déduire l'égalité de l'identité
Si
is
c'est vrai, l'égalité peut généralement être déduite - logiquement, si un objet est lui-même, il doit alors être testé comme équivalent à lui-même.Dans la plupart des cas, cette logique est vraie, mais elle repose sur la mise en œuvre de la
__eq__
méthode spéciale. Comme le disent les docs ,et dans un souci de cohérence, recommande:
Nous pouvons voir que c'est le comportement par défaut pour les objets personnalisés:
La contrapositive est également généralement vraie - si quelque chose est différent, vous pouvez généralement déduire qu'il ne s'agit pas du même objet.
Étant donné que les tests d'égalité peuvent être personnalisés, cette inférence n'est pas toujours vraie pour tous les types.
Une exception
Une exception notable est
nan
- il teste toujours comme différent de lui-même:La vérification de l'identité peut être beaucoup plus rapide que la vérification de l'égalité (ce qui peut nécessiter une vérification récursive des membres).
Mais il ne peut pas être substitué à l'égalité où vous pouvez trouver plus d'un objet comme équivalent.
Notez que la comparaison de l'égalité des listes et des tuples supposera que l'identité des objets est égale (car il s'agit d'une vérification rapide). Cela peut créer des contradictions si la logique est incohérente - comme c'est le cas pour
nan
:Un récit édifiant:
La question tente d'utiliser
is
pour comparer des entiers. Vous ne devez pas supposer qu'une instance d'un entier est la même instance que celle obtenue par une autre référence. Cette histoire explique pourquoi.Un commentateur avait du code qui reposait sur le fait que les petits entiers (-5 à 256 inclus) sont des singletons en Python, au lieu de vérifier l'égalité.
Cela a fonctionné dans le développement. Il a peut-être réussi certains tests.
Et cela a fonctionné en production - jusqu'à ce que le code vérifie un entier supérieur à 256, moment auquel il a échoué en production.
Il s'agit d'un échec de production qui aurait pu être détecté dans la révision du code ou éventuellement avec un vérificateur de style.
Permettez-moi de souligner: ne pas utiliser
is
pour comparer des entiers.la source
is None
étant une exception, mais cela dit ça== None
marche aussi ...is
pour comparer l'Enum
art.Quelle est la différence entre
is
et==
?==
etis
sont une comparaison différente! Comme d'autres l'ont déjà dit:==
compare les valeurs des objets.is
compare les références des objets.En Python, les noms font référence aux objets, par exemple dans ce cas
value1
etvalue2
font référence à uneint
instance stockant la valeur1000
:Parce que
value2
fait référence au même objetis
et==
donneraTrue
:Dans l'exemple suivant, les noms
value1
et lesvalue2
références à différentesint
instances, même si les deux stockent le même entier:Parce que est stockée la même valeur (entier)
==
seraTrue
, c'est pourquoi il est souvent appelé « comparaison de la valeur ». Cependantis
reviendraFalse
car ce sont des objets différents:Quand utiliser quoi?
is
Est généralement une comparaison beaucoup plus rapide. C'est pourquoi CPython met en cache (ou peut-être réutiliser serait le meilleur terme) certains objets comme les petits entiers, certaines chaînes, etc. Mais cela devrait être traité comme un détail d'implémentation qui pourrait (même si cela est peu probable) changer à tout moment sans avertissement.Vous ne devez utiliser que
is
si vous:veulent comparer une valeur à une constante Python . Les constantes en Python sont:
None
True
1False
1NotImplemented
Ellipsis
__debug__
int is int
ouint is float
)np.ma.masked
partir du module NumPy)Dans tous les autres cas, vous devez utiliser
==
pour vérifier l'égalité.Puis-je personnaliser le comportement?
Il y a un aspect
==
qui n'a pas déjà été mentionné dans les autres réponses: il fait partie du "modèle de données" Pythons . Cela signifie que son comportement peut être personnalisé à l'aide de la__eq__
méthode. Par exemple:Ceci est juste un exemple artificiel pour illustrer que la méthode est vraiment appelée:
Notez que par défaut (si aucune autre implémentation de
__eq__
ne peut être trouvée dans la classe ou les superclasses)__eq__
utiliseis
:Il est donc important d'implémenter
__eq__
si vous voulez "plus" qu'une simple comparaison de références pour les classes personnalisées!En revanche, vous ne pouvez pas personnaliser les
is
chèques. Il sera toujours comparé juste si vous avez la même référence.Ces comparaisons renverront-elles toujours un booléen?
Parce qu'il
__eq__
peut être réimplémenté ou remplacé, il n'est pas limité à retournerTrue
ouFalse
. Il pourrait renvoyer n'importe quoi (mais dans la plupart des cas, il devrait renvoyer un booléen!).Par exemple, avec les tableaux NumPy, le
==
renvoie un tableau:Mais les
is
chèques reviendront toujoursTrue
ouFalse
!1 Comme Aaron Hall l'a mentionné dans les commentaires:
En règle générale, vous ne devriez pas effectuer de vérifications
is True
ouis False
parce que l'on utilise normalement ces «vérifications» dans un contexte qui convertit implicitement la condition en booléen (par exemple dans uneif
instruction). Donc, faire lais True
comparaison et la distribution booléenne implicite fait plus de travail que simplement faire la distribution booléenne - et vous vous limitez aux booléens (qui n'est pas considéré comme pythonique).Comme PEP8 le mentionne:
la source
is
- les noms qui pointent vers des booléens devraient être vérifiés avec un contexte booléen - commeif __debug__:
ouif not __debug__:
. Vous ne devriez jamais faireif __debug__ is True:
ouif __debug__ == True:
- en outre, une constante est simplement une valeur sémantique constante, pas un singleton, donc vérifier avecis
dans ce cas n'est pas sémantiquement correct. Je vous mets au défi de trouver une source pour étayer vos affirmations - je ne pense pas que vous en trouverez une.None
,True
,False
et__debug__
sont ce que vous appelez « valeur sémantique constante », parce qu'ils ne peuvent pas être réaffectés. Mais tous sont des singletons.is True
ou de laif False
vérification (mais oui, ce sont assez rares - mais si vous les faites, vous pouvez les faire en utilisantis
). C'est pourquoi même CPython les utilise parfois (par exemple ici ou ici )Ils sont complètement différents .
is
vérifie l'identité de l'objet, tandis que==
vérifie l'égalité (une notion qui dépend des types des deux opérandes).Ce n'est qu'une heureuse coïncidence que "
is
" semble fonctionner correctement avec de petits nombres entiers (par exemple 5 == 4 + 1). C'est parce que CPython optimise le stockage des entiers dans la plage (-5 à 256) en les faisant singletons . Ce comportement est totalement dépendant de l'implémentation et n'est pas garanti d'être conservé sous toutes sortes d'opérations de transformation mineures.Par exemple, Python 3.5 crée également des singletons de chaînes courtes, mais leur découpage perturbe ce comportement:
la source
https://docs.python.org/library/stdtypes.html#comparisons
is
tests d'identité==
tests d'égalitéChaque (petit) nombre entier est mappé sur une seule valeur, donc tous les 3 sont identiques et égaux. Ceci est un détail d'implémentation, mais ne fait pas partie des spécifications de langue
la source
Votre réponse est correcte. L'
is
opérateur compare l'identité de deux objets. L'==
opérateur compare les valeurs de deux objets.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.
Vous pouvez contrôler le comportement de comparaison des valeurs d'objet en définissant une
__cmp__
méthode ou une méthode de comparaison riche comme__eq__
.la source
Jetez un œil à la question Stack Overflow L'opérateur «is» de Python se comporte de manière inattendue avec des entiers .
Ce qui revient essentiellement à "
is
" vérifier si ce sont les mêmes objets, pas seulement égaux les uns aux autres (les nombres en dessous de 256 sont un cas particulier).la source
En bref,
is
vérifie si deux références pointent vers le même objet ou non.==
vérifie si deux objets ont la même valeur ou non.la source
Comme l'a dit John Feminella, la plupart du temps, vous utiliserez == et! = Car votre objectif est de comparer les valeurs. Je voudrais simplement classer ce que vous feriez le reste du temps:
Il existe une et une seule instance de NoneType, c'est-à-dire que None est un singleton. Par conséquent
foo == None
etfoo is None
signifient la même chose. Cependant, leis
test est plus rapide et la convention Pythonic est à utiliserfoo is None
.Si vous effectuez une introspection ou un nettoyage avec la collecte des ordures ou vérifiez si votre gadget d'internement de chaînes personnalisé fonctionne ou similaire, alors vous avez probablement un cas d'utilisation pour
foo
isbar
.Vrai et Faux sont également (maintenant) des singletons, mais il n'y a pas de cas d'
foo == True
utilisation ni de cas d'utilisation pourfoo is True
.la source
La plupart d'entre eux ont déjà répondu au point. Tout comme une note supplémentaire (basée sur ma compréhension et mes expériences mais pas à partir d'une source documentée), la déclaration
des réponses ci-dessus doivent être lues comme
. Je suis arrivé à cette conclusion sur la base du test ci-dessous:
Ici, le contenu de la liste et du tuple sont identiques mais le type / classe est différent.
la source
Différence Python entre is et equals (==)
Voici un exemple pour démontrer la similitude et la différence.
la source
Comme les autres personnes de ce message répondent en détail à la question, je soulignerais principalement la comparaison entre
is
et==
pour les chaînes qui peuvent donner des résultats différents et j'exhorte les programmeurs à les utiliser avec soin.Pour la comparaison de chaînes, assurez-vous d'utiliser
==
au lieu deis
:En dehors:
Mais dans l'exemple ci-dessous
==
etis
obtiendra des résultats différents:En dehors:
Conclusion:
Utilisez
is
soigneusement pour comparer les chaînesla source