337 votes

Python! = Operation vs "n'est pas"

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 était la différence et pourquoi l'une d'elles pouvait être recommandée plutôt que l'autre?

Merci!

372voto

Thomas Wouters Points 38811

== est un test d'égalité. Il vérifie si le côté droit et le côté gauche sont les objets égaux (en fonction de leur __eq__ ou __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. Pas de methodcalls sont fait, les objets ne peut pas influencer l' is de l'opération.

Vous utilisez is (et is not) pour les singletons, comme None, où vous n'avez pas de soins sur les objets qui pourraient vouloir faire semblant d'être None ou lorsque vous souhaitez protéger contre les objets de la rupture lors de l'été comparée None.

180voto

Wesley Points 5664

Tout d'abord, permettez-moi de passer en revue quelques termes. Si vous voulez juste la réponse à votre question, faites défiler jusqu'à "Répondre à votre question".

Définitions

L'identité de l'objet: Lorsque vous créez un objet, vous pouvez l'affecter à une variable. Ensuite, vous pouvez aussi l'attribuer à une autre variable. Et de l'autre.

>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True

Dans ce cas, cancel, close, et dismiss tous les font référence au même objet en mémoire. Vous n'créé un Button objet, et tous les trois variables se rapportent à cet objet. Nous disons qu' cancel, close, et dismiss se réfèrent tous à l' identique des objets; qui est, ils se réfèrent à un seul objet.

Objet de l'égalité: Lorsque vous comparez les deux objets, vous n'avez généralement pas de soins qu'il se réfère à l' exact même objet en mémoire. Avec l'objet de l'égalité, vous pouvez définir vos propres règles pour deux objets à comparer. Lorsque vous écrivez if a == b:, vous êtes essentiellement en disant: if a.__eq__(b):. Cela vous permet de définir un __eq__ méthode a , de sorte que vous pouvez utiliser votre propre logique de comparaison.

Justification pour l'égalité des comparaisons

Justification:les 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: Les Chaînes De

>>> 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 parce que Python est assez intelligent pour réutiliser régulièrement des cordes sans en créer de nouveaux dans la mémoire.

Ici, j'ai deux chaînes unicode, a et 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 comparer l'égalité. Ce qui se passe ici est que l'unicode objet est mis en œuvre l' __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__ sur unicode est certainement mis en œuvre de manière plus efficace que cela.

Justification:les Deux objets ont des données différentes, mais sont considérés comme l'objet même si certaines données clés est la même. Exemple: la Plupart des types de modèle de données

>>> 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 écrans Dell, a et b. Ils ont la même marque et le 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 comparer l'égalité. Ce qui se passe ici est que le Moniteur de l'objet mis en œuvre l' __eq__ méthode.

class Monitor(object):
    # ...

    def __eq__(self, other):
        return self.make == other.make and self.model == other.model

Pour répondre à votre question

Lors de la comparaison d' None, toujours utiliser is not. Aucun n'est un singleton en Python - il n'y a qu'une seule occurrence dans la mémoire.

En comparant l'identité, cela peut être réalisé très rapidement. Python vérifie si l'objet vous faites allusion a la même adresse mémoire mondial Aucun objet - une très, très vite, la comparaison de deux nombres.

En comparant l'égalité, Python a de chercher si votre objet a un __eq__ méthode. Si elle ne le fait pas, il examine chaque super-classe à la recherche d'un __eq__ méthode. Si il en trouve un, Python appelle. Cela est particulièrement mauvais si l' __eq__ méthode est lente et ne pas retourner immédiatement lorsqu'il constate que l'autre objet est de None.

N'avez-vous pas mettre en oeuvre __eq__? Ensuite Python trouverez probablement la __eq__ méthode object et l'utiliser au lieu - vérifie l'identité de l'objet, de toute façon.

Lors de la comparaison de la plupart des autres choses en Python, vous serez en utilisant !=.

50voto

Alok Singhal Points 33073
Considérez les aspects suivants :

25voto

None est un singleton, donc la comparaison d'identité fonctionnera toujours, alors qu'un objet peut simuler la comparaison d'égalité via .__eq__() .

11voto

ephemient Points 87003
>>> () est ()
Vrai
>>> 1 est 1
Vrai
>>> (1,) == (1,)
Vrai
>>> (1,) est (1,)
Faux
>>> a = (1,)
>>> b = a
>>> a est b
Vrai

Certains objets sont des singletons et ainsi, is avec eux équivaut à == . La plupart ne le sont pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X