Question Y a-t-il une différence entre `==` et `is` dans Python?


ma Google-fu a échoué.

En Python, les deux tests suivants sont-ils équivalents pour l'égalité?

n = 5
# Test one.
if n == 5:
    print 'Yay!'

# Test two.
if n is 5:
    print 'Yay!'

Est-ce que ceci est vrai pour les objets où vous compareriez des instances (un list dire)?

Ok, 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.

Alors == teste la valeur là où is tests pour voir si elles sont le même objet?


516
2017-09-25 12:27


origine


Réponses:


is reviendra True si deux variables pointent vers le même objet, == si les objets référencés par les variables sont égaux.

>>> a = [1, 2, 3]
>>> b = a
>>> b is a 
True
>>> b == a
True
>>> b = a[:]
>>> b is a
False
>>> b == a
True

Dans votre cas, le second test ne fonctionne que parce que Python met en cache de petits objets entiers, ce qui est un détail d'implémentation. Pour les entiers plus grands, cela ne fonctionne pas:

>>> 1000 is 10**3
False
>>> 1000 == 10**3
True

La même chose vaut pour les littéraux de chaîne:

>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True

S'il te plait regarde cette question ainsi que.


713
2017-09-25 12:32



Il existe une règle simple pour vous dire quand utiliser == ou is.

  • == est pour valeur égalité. Utilisez-le lorsque vous souhaitez savoir si deux objets ont la même valeur.
  • is est pour égalité de référence. Utilisez-le lorsque vous souhaitez savoir si deux références se réfèrent au même objet.

En général, lorsque vous comparez quelque chose à un type simple, vous vérifiez généralement valeur égalité, donc vous devriez utiliser ==. Par exemple, l'intention de votre exemple est probablement de vérifier si x a une valeur égale à 2 (==), pas si x fait littéralement référence au même objet que 2.


Autre chose à noter: à cause de la façon dont l'implémentation de référence de CPython fonctionne, vous obtiendrez des résultats inattendus et incohérents si vous utilisez par erreur is comparer pour l'égalité de référence sur les entiers:

>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False

C'est à peu près ce que nous attendions: a et b ont la même valeur, mais sont des entités distinctes. Mais qu'en est-il de ça?

>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True

Ceci 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 démontrant ceci:

>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));
... 
250: True
251: True
252: True
253: True
254: True
255: True
256: True
257: False
258: False
259: False

Ceci 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.


229
2017-07-06 06:22



== détermine si les valeurs sont égales, tandis que is détermine si elles sont exactement le même objet et égal.


22
2017-09-25 12:31



Elles sont complètement différent. is vérifie l'identité de l'objet, == vérifie l'égalité (notion qui dépend des types des deux opérandes).

Ce n'est qu'une coïncidence heureuse "is"semble fonctionner correctement avec de petits nombres entiers (par exemple 5 == 4 + 1). CPython optimise le stockage des entiers dans la gamme (-5 à 256) en les rendant singletons. Ce comportement est totalement dépendant de l'implémentation et n'est pas garanti pour être conservé sous toutes les opérations de transformation mineures.

Par exemple, Python 3.5 fait également des singletons à chaînes courtes, mais les découper les perturbe:

>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False

12
2017-09-25 17:15



Y a-t-il une différence entre == et is en Python?

Oui, ils ont une différence très importante.

==: vérifie l'égalité - la sémantique est que les objets équivalents (qui ne sont pas nécessairement le même objet) seront testés égaux. Comme le la documentation dit:

Les opérateurs <,>, ==,> =, <=, et! = Comparent les valeurs de deux objets.

is: vérifier l'identité - la sémantique est que l'objet (comme en mémoire) est L'object. Encore une fois, le la documentation dit:

Les opérateurs is et is not test d'identité d'objet: x is y est vrai   si et seulement si x et y sont le même objet. L'identité de l'objet est   déterminé en utilisant le id() fonction. x is not y donne l'inverse   valeur de vérité.

Ainsi, la vérification de l'identité est la même que la vérification de l'égalité des ID des objets. C'est,

a is b

est le même que:

id(a) == id(b)

id est la fonction intégrée qui renvoie un entier qui "est garanti unique parmi les objets existants simultanément" (voir help(id)) et où a et b sont des objets arbitraires.

Autres instructions d'utilisation

Vous devriez utiliser ces comparaisons pour leur sémantique. Utilisation is vérifier l'identité et == pour vérifier l'égalité.

PEP 8, le guide de style officiel Python pour la bibliothèque standard mentionne également deux cas d'utilisation pour is:

Des comparaisons avec des singletons comme None devrait toujours être fait avec is ou    is not, jamais les opérateurs d'égalité.

Aussi, méfiez-vous de l'écriture if x quand tu veux vraiment dire if x is not None -   par exemple. lors du test si une variable ou un argument par défaut None   a été mis à une autre valeur. L'autre valeur peut avoir un type (tel   comme un conteneur) qui pourrait être faux dans un contexte booléen!

En déduire l'égalité de l'identité

Si is est vrai, l'égalité peut d'habitude être déduit - logiquement, si un objet est lui-même, alors il devrait tester comme équivalent à lui-même.

Dans la plupart des cas, cette logique est vraie, mais elle repose sur la mise en __eq__ méthode spéciale. Comme le docs dire,

Le comportement par défaut pour la comparaison d'égalité (== et !=) est basé sur   l'identité des objets. Par conséquent, la comparaison d'égalité des instances   avec la même identité résulte en l'égalité, et la comparaison de l'égalité de   les instances ayant des identités différentes entraînent des inégalités. UNE   la motivation pour ce comportement par défaut est le désir que tous les objets   devrait être réflexif (c'est-à-dire que x est y implique x == y).

et par souci de cohérence, recommande:

La comparaison de l'égalité doit être réfléchie. En d'autres termes, identique   les objets doivent être égaux:

x is y implique x == y

Nous pouvons voir que c'est le comportement par défaut pour les objets personnalisés:

>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)

La contrapositive est aussi généralement vraie - si quelque chose ne se vérifie pas, vous pouvez généralement déduire que ce n'est pas le même objet.

Puisque 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 n'étant pas égal à lui-même:

>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan           # !!!!!
False

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 comparer l'égalité des listes et des tuples supposera que l'identité des objets est égale (parce que c'est une vérification rapide). Cela peut créer des contradictions si la logique est incohérente - comme c'est le cas pour nan:

>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True

Un conte de mise en garde:

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 un 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é.

Wow, cela peut conduire à des bugs insidieux. J'avais du code qui vérifiait si a est b, ce qui fonctionnait comme je le voulais car a et b sont typiquement de petits nombres. Le bug est arrivé seulement aujourd'hui, après six mois de production, parce que a et b étaient finalement assez grands pour ne pas être mis en cache. - gwg

Cela a marché dans le développement. Il a peut-être passé des moments inacceptables.

Et cela a fonctionné en production - jusqu'à ce que le code vérifié pour un nombre entier supérieur à 256, à quel point il a échoué en production.

Il s'agit d'un problème de production qui aurait pu être détecté dans la révision de code ou éventuellement avec un vérificateur de style.

Laissez-moi souligner: ne pas utiliser is pour comparer des entiers.


10
2018-01-05 19:33



https://docs.python.org/library/stdtypes.html#comparisons

is tests d'identité == tests pour l'égalité

Chaque (entier) valeur entière est mappée à une valeur unique, donc chaque 3 est identique et égal. Ceci est un détail de mise en œuvre, ne fait pas partie de la spécification de la langue si


8
2017-09-25 12:31



Quelle est la différence entre is et ==?

== et is sont la comparaison différente! Comme d'autres l'ont déjà dit:

  • == compare les valeurs des objets.
  • is compare les références des objets.

Dans les noms Python se référer à des objets, par exemple dans ce cas value1 et value2 se référer à un int instance stockant la valeur 1000:

value1 = 1000
value2 = value1

enter image description here

Car value2 se réfère au même objet is et == va donner True:

>>> value1 == value2
True
>>> value1 is value2
True

Dans l'exemple suivant les noms value1 et value2 se référer à différents int instances, même si les deux stockent le même entier:

>>> value1 = 1000
>>> value2 = 1000

enter image description here

Parce que la même valeur (entier) est stockée == sera True, c'est pourquoi on l'appelle souvent "comparaison de valeur". toutefois is reviendra False parce que ce sont des objets différents:

>>> value1 == value2
True
>>> value1 is value2
False

Quand utiliser quoi?

Généralement is est une comparaison beaucoup plus rapide. C’est pourquoi caches CPython (ou peut-être réutilise serait le meilleur terme) certains objets comme les petits entiers, certaines chaînes, etc. Mais cela devrait être traité comme détail d'implémentation cela pourrait (même si peu probable) changer à tout moment sans avertissement.

Vous devriez Usage unique is si tu:

  • vouloir vérifier si deux objets sont vraiment le même objet (pas seulement la même "valeur"). Un exemple peut être si toi utilise un objet singleton comme constante.
  • vouloir comparer une valeur à un Python constant. Les constantes dans Python sont:

    • None
    • True1
    • False1
    • NotImplemented
    • Ellipsis
    • __debug__
    • classes (par exemple int is int ou int is float)
    • il pourrait y avoir des constantes supplémentaires dans les modules intégrés ou les modules tiers. Par exemple np.ma.masked à partir du module NumPy)

Dans tous les autres cas, vous devriez utiliser == pour vérifier l'égalité.

Puis-je personnaliser le comportement?

Il y a un aspect à == cela n'a pas déjà été mentionné dans les autres réponses: Cela fait partie de Pythons "Modèle de données". Cela signifie que son comportement peut être personnalisé en utilisant le __eq__ méthode. Par exemple:

class MyClass(object):
    def __init__(self, val):
        self._value = val

    def __eq__(self, other):
        print('__eq__ method called')
        try:
            return self._value == other._value
        except AttributeError:
            raise TypeError('Cannot compare {0} to objects of type {1}'
                            .format(type(self), type(other)))

Ceci est juste un exemple artificiel pour illustrer que la méthode est vraiment appelée:

>>> MyClass(10) == MyClass(10)
__eq__ method called
True

Notez que par défaut (si aucune autre implémentation de __eq__ peut être trouvé dans la classe ou les superclasses) __eq__ les usages is:

class AClass(object):
    def __init__(self, value):
        self._value = value

>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a

Il est donc important de mettre en œuvre __eq__ Si vous voulez "plus" que juste comparaison de référence pour les classes personnalisées!

Par contre vous ne pouvez pas personnaliser is vérifications. Il va toujours comparer juste si vous avez la même référence.

Est-ce que ces comparaisons retourneront toujours un booléen?

Car __eq__ peut être ré-implémenté ou remplacé, il n'est pas limité à retourner True ou False. Il pourrait retourner quelque chose (mais dans la plupart des cas, il devrait retourner un booléen!).

Par exemple avec les tableaux NumPy le == retournera un tableau:

>>> import numpy as np
>>> np.arange(10) == 2
array([False, False,  True, False, False, False, False, False, False, False], dtype=bool)

Mais is les chèques reviendront toujours True ou False!


1 Comme Aaron Hall l'a mentionné dans les commentaires:

En général, vous ne devriez pas faire is True ou is False vérifie parce que l'on utilise normalement ces "vérifications" dans un contexte qui convertit implicitement condition à un booléen (par exemple dans un if déclaration). Donc faire le is True Comparaison et le casting booléenne implicite fait plus de travail que de simplement faire le casting booléenne - et vous vous limiter à booléens (qui est pas considéré pythonique).

Comme les mentions PEP8:

Ne comparez pas les valeurs booléennes à True ou False en utilisant ==.

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:

6
2018-01-19 22:21



Votre réponse est correcte. le is L'opérateur compare l'identité de deux objets. le == 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 un __cmp__ méthode ou un comparaison riche méthode comme __eq__.


5
2017-09-25 12:34



Jetez un oeil à la question Stack Overflow L'opérateur "is" de Python se comporte de façon inattendue avec des nombres entiers.

Qu'est-ce qu'il se résume le plus à c'est que "is"vérifie pour voir s'il s'agit du même objet, pas seulement égal à l'autre (les nombres inférieurs à 256 sont un cas particulier).


3
2017-07-06 06:20



Comme John Feminella l'a dit, vous utiliserez la plupart du temps == et! = Car votre objectif est de comparer les valeurs. Je voudrais juste catégoriser ce que vous feriez le reste du temps:

Il y a une et une seule instance de NoneType, c'est-à-dire None est un singleton. par conséquent foo == None et foo is None signifie la même chose. Cependant, le is le test est plus rapide et la convention Pythonic est d'utiliser foo is None.

Si vous faites de l'introspection ou de la collecte de place ou si vous vérifiez si votre gadget d'internalisation de chaîne personnalisé fonctionne ou non, vous avez probablement un cas d'utilisation pour foo est bar.

Vrai et Faux sont aussi (maintenant) des singletons, mais il n'y a pas de cas d'utilisation pour foo == True et aucun cas d'utilisation pour foo is True.


1
2017-07-06 08:50