web-dev-qa-db-fra.com

Y a-t-il une différence entre "==" et "est"?

Mon Google-fu m'a échoué.

En Python, les deux tests suivants d’égalité sont-ils équivalents?

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

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

Cela est-il vrai pour les objets pour lesquels vous compareriez des instances (un list dire)?

Bon, alors ce genre de réponse à ma question:

L = []
L.append(1)
if L == [1]:
    print 'Yay!'
# Holds true, but...

if L is [1]:
    print 'Yay!'
# Doesn't.

Donc, == teste la valeur où is teste pour voir s’il s’agit du même objet?

572
Bernard

is retournera True si deux variables pointent sur le même objet, == si les objets auxquels les variables font référence sont égaux.

>>> a = [1, 2, 3]
>>> b = a
>>> b is a 
True
>>> b == a
True
>>> b = a[:] # Make a new copy of list `a` via the slice operator, and assign it to variable `b`
>>> b is a
False
>>> b == a
True

Dans votre cas, le deuxième 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

Il en va de même 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 vous plaît voir cette question ainsi.

785
Torsten Marek

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 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é de valeur, vous devez donc utiliser ==. Par exemple, l'objectif de votre exemple est probablement de vérifier si x a une valeur égale à 2 (==), et non si x fait littéralement référence au même objet que 2.


Autre chose à noter: en raison de la manière dont l’implémentation de référence CPython fonctionne, 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:

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

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

>>> 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 des objets entiers de cache Python 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

C'est une autre raison évidente de ne pas utiliser is: le comportement est laissé à l'implémentation lorsque vous l'utilisez par erreur pour l'égalité des valeurs.

263
John Feminella

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

29
stephenbayer

Existe-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 indique que les objets équivalents (qui ne sont pas nécessairement le même objet) seront testés comme étant égaux. Comme le la documentation dit }:

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

is: vérifie l'identité - la sémantique indique que l'objet (conservé en mémoire) est l'objet. Encore une fois, le la documentation dit :

Les opérateurs is et is not testent l'identité de l'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é à l'aide de la fonction id(). x is not y donne l'inverse valeur de vérité.

Ainsi, la vérification de l'identité est la même chose 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 "a la garantie d'être unique parmi les objets simultanément existants" (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. Utilisez is pour vérifier l’identité et == pour vérifier l’égalité.

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

Les comparaisons avec des singletons comme None devraient toujours être faites avec is ou is not, jamais les opérateurs d'égalité.

Aussi, méfiez-vous de l'écriture if x lorsque vous voulez vraiment dire if x is not None -- par exemple. lorsque vous testez si une variable ou un argument dont la valeur par défaut est None a été mis à une autre valeur. L'autre valeur peut avoir un type (tel que En tant que conteneur) qui peut être faux dans un contexte booléen!

Déduire l'égalité de l'identité

Si is est vrai, l'égalité peut généralement être inférée - 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 méthode spéciale __eq__. Comme le docs _ dit, 

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é aboutit à l'égalité et à la comparaison d'égalité de des instances d'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.-à-d. que x est y implique x == y).

et dans un souci de cohérence, recommande:

La comparaison d'égalité devrait être réflexive. En d'autres termes, identique les objets doivent être comparés égaux:

x is y implique x == y

Nous pouvons voir qu'il s'agit du 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 également généralement vraie - si certains critères ne sont pas égaux, vous pouvez généralement en déduire qu'ils ne sont pas le même objet. 

Comme 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:

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

La vérification de l'identité peut être une vérification beaucoup plus rapide que la vérification de l'égalité (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 équivalent.

Notez que la comparaison de l'égalité des listes et des tuples suppose que l'identité des objets est la même (car il s'agit d'une vérification rapide). Cela peut créer des contradictions si la logique est incohérente - comme pour nan:

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

Un récit d'avertissement

La question tente d'utiliser is pour comparer des nombres entiers. Vous ne devriez 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 reposant 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'ai eu un code qui vérifiait si a est b, ce qui a fonctionné comme je voulais parce que a et b sont généralement de petits nombres. Le bogue n’est apparu qu’aujourd’hui, après six mois de production, car a et b étaient finalement assez gros pour ne pas être mis en cache. - gwg

Cela a fonctionné en développement. Il a peut-être passé quelques ennuis. 

Et cela a fonctionné en production - jusqu'à ce que le code vérifie la présence d'un entier supérieur à 256, point auquel il a échoué en production. 

Il s'agit d'une défaillance de production qui aurait pu être détectée lors de la révision du code ou éventuellement avec un vérificateur de style.

Permettez-moi de souligner: N'UTILISEZ PAS is POUR COMPARER DES NOMBRES ENTIERS.

20
Aaron Hall

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

Ce n'est que par hasard que "is" semble fonctionner correctement avec de petits entiers (par exemple 5 == 4 + 1). En effet, CPython optimise le stockage des entiers compris entre -5 et 256 en les transformant en singletons . Ce comportement dépend totalement de la mise en œuvre et il n'est pas garanti qu'il soit conservé dans toutes les 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:

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

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

is teste l'identité == teste l'égalité

Chaque (petit) nombre entier est mappé à une valeur unique, donc chaque 3 est identique et égal. Il s’agit d’un détail d’implémentation, ne faisant pas partie des spécifications de langage.

10
mmaibaum

Votre réponse est correcte. L'opérateur is 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 méthode __cmp__ ou une méthode rich Comparison telle que __eq__.

6
Dave Webb

Jetez un coup d'œil à la question de débordement de pile L'opérateur «is» de Python se comporte de manière inattendue avec les entiers.

Cela revient essentiellement à dire que "is" vérifie s'il s'agit du même objet, pas seulement égal les uns aux autres (les nombres inférieurs à 256 constituent un cas particulier).

4
cobbal

L'opérateur == compare les valeurs des deux opérandes et vérifie leur égalité. Alors que is, l'opérateur vérifie si les deux opérandes se réfèrent ou non au même objet.

a = [1,2,3,4]
b = a
print(a == b) # true
print(a is b) # true

Mais si nous faisons

b = a[:] # b now references a copy of a
print(a == b) # true
print(a is b) # false
print(a is not b) # true

is peut être considéré comme un raccourci pour id(a) == id(b). Cependant, au-delà, il existe des particularités de l'environnement d'exécution qui compliquent davantage les choses. Les chaînes courtes et les petits entiers renverrontTruepar rapport à is, car la machine Python tente d'utiliser moins de mémoire pour des objets identiques.

a = 'python'
b = 'python'

print(a == b) # true
print(a is b) # true
3
SkyNet

La plupart d'entre eux ont déjà répondu au point. Juste comme note supplémentaire (basée sur ma compréhension et mes expériences mais pas sur une source documentée), la déclaration 

== si les objets référencés par les variables sont égaux

à partir des réponses ci-dessus doit être lu comme 

== si les objets référencés par les variables sont égaux et les objets appartenant au même type/classe

. Je suis arrivé à cette conclusion sur la base du test ci-dessous:

list1 = [1,2,3,4]
Tuple1 = (1,2,3,4)

print(list1)
print(Tuple1)
print(id(list1))
print(id(Tuple1))

print(list1 == Tuple1)
print(list1 is Tuple1)

Ici, le contenu de la liste et du tuple sont identiques mais le type/classe est différent. 

2
Sandeep

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

Il n’existe qu’une et une seule instance de NoneType, c’est-à-dire que None est un singleton. Par conséquent, foo == None et foo is None signifient la même chose. Cependant, le test is est plus rapide et la convention Pythonic consiste à utiliser foo is None.

Si vous faites de l'introspection ou du nettoyage de votre mémoire, ou si vous vérifiez si votre gadget d'internement de chaîne personnalisé fonctionne, vous avez probablement un scénario d'utilisation pour foo est bar.

True et False sont également (maintenant) des singletons, mais il n'y a pas de cas d'utilisation pour foo == True ni de cas d'utilisation pour foo is True

2
John Machin

En un mot, 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.

a=[1,2,3]
b=a        #a and b point to the same object
c=list(a)  #c points to different object 

if a==b:
    print('#')   #output:#
if a is b:
    print('##')  #output:## 
if a==c:
    print('###') #output:## 
if a is c:
    print('####') #no output as c and a point to different object 
2
suvojit_007

En fait, je voulais ajouter ceci en tant que commentaire mais je ne pouvais pas l'embellir facilement, donc en ajoutant une réponse, veuillez ne pas considérer cela comme une réponse. 

C'est ce que j'ai fait pour comprendre -

exécuter en suivant un par un et comprendre la sortie à chaque étape

a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b
1
Pranav

Comme les autres personnes de cet article répondent à la question en détail, je souligne principalement la comparaison entre is et == pour les chaînes qui peuvent donner des résultats différents et j'encourage les programmeurs à les utiliser avec précaution.

Pour comparer les chaînes, veillez à utiliser == au lieu de is:

str = 'hello'
if (str is 'hello'):
    print ('str is hello')
if (str == 'hello'):
    print ('str == hello')

En dehors:

str is hello
str == hello

Mais dans l'exemple ci-dessous, == et is obtiendront des résultats différents:

str = 'hello sam'
    if (str is 'hello sam'):
        print ('str is hello sam')
    if (str == 'hello sam'):
        print ('str == hello sam')

En dehors:

str == hello sam

Conclusion:

Utilisez is avec soin pour comparer les chaînes 

1
imanzabet

Différence en python entre is et égaux (==)

L'opérateur is peut sembler identique à l'opérateur d'égalité, mais ils ne sont pas pareils.

La vérifie si les deux variables pointent sur le même objet alors que le signe == vérifie si les valeurs des deux variables sont identiques.

Donc, si l'opérateur is retourne True, l'égalité est définitivement Vrai, mais le contraire peut être vrai ou non.

Voici un exemple pour démontrer la similitude et la différence.

>>> a = b = [1,2,3]
>>> c = [1,2,3]
>>> a == b
True
>>> a == c
True
>>> a is b
True
>>> a is c
False
>>> a = [1,2,3]
>>> b = [1,2]
>>> a == b
False
>>> a is b
False
>>> del a[2]
>>> a == b
True
>>> a is b
False
Tip: Avoid using is operator for immutable types such as strings and numbers, the result is unpredictable.
0
Projesh Bhoumik

Si vous le comparez avec JavaScript (il n'est toutefois pas recommandé de comparer une langue à une autre)

  • Utilisez is pour une comparaison stricte. Équivalent Javascript (===)
  • Utilisez == pour la comparaison d'égalité.
0