Dans un commentaire sur cette question , j'ai vu une déclaration qui recommandait d'utiliser
result is not None
contre
result != None
Je me demandais quelle est la différence et pourquoi l'une pourrait être recommandée par rapport à l'autre?
Dans un commentaire sur cette question , j'ai vu une déclaration qui recommandait d'utiliser
result is not None
contre
result != None
Je me demandais quelle est la différence et pourquoi l'une pourrait être recommandée par rapport à l'autre?
Réponses:
==
est un test d'égalité . Il vérifie si le côté droit et le côté gauche sont des objets égaux (selon leur__eq__
ou leurs__cmp__
méthodes.)is
est un test d'identité . Il vérifie si le côté droit et le côté gauche sont le même objet. Aucun appel de méthode n'est effectué, les objets ne peuvent pas influencer l'is
opération.Vous utilisez
is
(etis not
) pour les singletons, par exempleNone
, lorsque vous ne vous souciez pas des objets qui pourraient prétendre êtreNone
ou lorsque vous souhaitez vous protéger contre la rupture d'objets lors de la comparaisonNone
.la source
None
a peu de méthodes et presque aucun attribut. Si votre__eq__
test attendait une méthode ou un attribut, il pourrait casser.def __eq__( self, other ): return self.size == other.size
. Par exemple, se cassera s'ilother
se trouveNone
.is
est comme Java==
. Python==
est comme Java.equals()
. Bien sûr, cela n'aide que si vous connaissez Java.is
c'est comme===
(très égal), et inversementis not
c'est comme!==
(pas exactement égal).is not
qu'un seul opérateur ou est-ce simplement en train de nier le résultat de l'is
intérieur commenot foo is bar
?Tout d'abord, permettez-moi de passer en revue quelques termes. Si vous souhaitez simplement obtenir une réponse à votre question, faites défiler la page jusqu'à "Répondre à votre question".
Définitions
Identité de l'objet : lorsque vous créez un objet, vous pouvez l'affecter à une variable. Vous pouvez ensuite également l'affecter à une autre variable. Et un autre.
Dans ce cas,
cancel
,close
etdismiss
tous se réfèrent au même objet en mémoire. Vous avez créé un seulButton
objet et les trois variables font référence à cet objet unique. Nous disons quecancel
,close
etdismiss
tous se réfèrent à des objets identiques ; c'est-à-dire qu'ils se réfèrent à un seul objet.Égalité d'objet : lorsque vous comparez deux objets, vous ne vous souciez généralement pas qu'il se réfère exactement au même objet en mémoire. Avec l'égalité des objets, vous pouvez définir vos propres règles de comparaison entre deux objets. Lorsque vous écrivez
if a == b:
, vous dites essentiellementif a.__eq__(b):
. Cela vous permet de définir une__eq__
méthodea
afin que vous puissiez utiliser votre propre logique de comparaison.Justification des comparaisons d'égalité
Justification: deux objets ont exactement les mêmes données, mais ne sont pas identiques. (Ils ne sont pas le même objet en mémoire.) Exemple: chaînes
Remarque: j'utilise des chaînes unicode ici car Python est suffisamment intelligent pour réutiliser des chaînes régulières sans en créer de nouvelles en mémoire.
Ici, j'ai deux chaînes unicode,
a
etb
. Ils ont exactement le même contenu, mais ils ne sont pas le même objet en mémoire. Cependant, lorsque nous les comparons, nous voulons qu'ils se comparent égaux. Ce qui se passe ici, c'est que l'objet unicode a implémenté la__eq__
méthode.Remarque:
__eq__
onunicode
est définitivement implémenté plus efficacement que cela.Justification: Deux objets ont des données différentes, mais sont considérés comme le même objet si certaines données clés sont identiques. Exemple: la plupart des types de données de modèle
Ici, j'ai deux moniteurs Dell
a
etb
. Ils ont la même marque et le même modèle. Cependant, ils n'ont ni les mêmes données ni le même objet en mémoire. Cependant, lorsque nous les comparons, nous voulons qu'ils se comparent égaux. Ce qui se passe ici, c'est que l'objet Monitor a implémenté la__eq__
méthode.Répondre à votre question
Lorsque vous comparez à
None
, utilisez toujoursis not
. Aucun n'est un singleton en Python - il n'y en a jamais qu'une seule en mémoire.En comparant l' identité , cela peut être effectué très rapidement. Python vérifie si l'objet auquel vous faites référence a la même adresse mémoire que l'objet global None - une comparaison très, très rapide de deux nombres.
En comparant l' égalité , Python doit vérifier si votre objet a une
__eq__
méthode. Si ce n'est pas le cas, il examine chaque superclasse à la recherche d'une__eq__
méthode. S'il en trouve un, Python l'appelle. Cela est particulièrement mauvais si la__eq__
méthode est lente et ne revient pas immédiatement lorsqu'elle remarque que l'autre objet l'estNone
.N'avez-vous pas mis en œuvre
__eq__
? Ensuite, Python trouvera probablement la__eq__
méthodeobject
et l'utilisera à la place - qui vérifie simplement l'identité de l'objet de toute façon.Lorsque vous comparez la plupart des autres choses en Python, vous utiliserez
!=
.la source
Considérer ce qui suit:
la source
None
est un singleton, donc la comparaison d'identité fonctionnera toujours, alors qu'un objet peut simuler la comparaison d'égalité via.__eq__()
.la source
None
, mais un comportement incorrect concernantNone
pourrait se produire comme effet secondaire de la mise en œuvre de l'égalité contre d'autres types. Ce ne sont pas tant des implications de sécurité que des implications de justesse.Certains objets sont singletons, et donc
is
avec eux est équivalent à==
. La plupart ne le sont pas.la source
()
et1
ne sont pas intrinsèquement singletons.-NSMALLNEGINTS <= n <= NSMALLPOSINTS
) et les tuples vides sont des singletons. En effet, ce n'est ni documenté ni garanti, mais il est peu probable qu'il change.