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.)
isest 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' isopération.
Vous utilisez is(et is not) pour les singletons, par exemple None, lorsque vous ne vous souciez pas des objets qui pourraient prétendre être Noneou lorsque vous souhaitez vous protéger contre la rupture d'objets lors de la comparaison None.
Nonea 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'il otherse trouve None.
isest comme Java ==. Python ==est comme Java .equals(). Bien sûr, cela n'aide que si vous connaissez Java.
isc'est comme ===(très égal), et inversement is notc'est comme !==(pas exactement égal).
is notqu'un seul opérateur ou est-ce simplement en train de nier le résultat de l' isintérieur comme not 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".
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.
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
Dans ce cas, cancel, closeet dismisstous se réfèrent au même objet en mémoire. Vous avez créé un seul Buttonobjet et les trois variables font référence à cet objet unique. Nous disons que cancel, closeet dismisstous 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 essentiellement if a.__eq__(b):. Cela vous permet de définir une __eq__méthode aafin que vous puissiez utiliser votre propre logique de comparaison.
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
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
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, aet b. 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.
class unicode(object):
# ...
def __eq__(self, other):
if len(self) != len(other):
return False
for i, j in zip(self, other):
if i != j:
return False
return True
Remarque: __eq__on unicodeest 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
>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True
Ici, j'ai deux moniteurs Dell aet b. 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.
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
Lorsque vous comparez à None, utilisez toujours is 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'est None.
N'avez-vous pas mis en œuvre __eq__? Ensuite, Python trouvera probablement la __eq__méthode objectet 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 !=.
Considérer ce qui suit:
class Bad(object):
def __eq__(self, other):
return True
c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)
Noneest un singleton, donc la comparaison d'identité fonctionnera toujours, alors qu'un objet peut simuler la comparaison d'égalité via .__eq__().
None, mais un comportement incorrect concernant Nonepourrait 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.
>>> () est () Vrai >>> 1 est 1 Vrai >>> (1,) == (1,) Vrai >>> (1,) est (1,) Faux >>> a = (1,) >>> b = a >>> a est b Vrai
Certains objets sont singletons, et donc isavec eux est équivalent à ==. La plupart ne le sont pas.
()et 1ne 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.