Est-il une différence entre `==` et `est` en Python?
Mon Google-fu m'a laissé tomber.
en Python, les deux tests suivants sont-ils équivalents?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
est-ce vrai pour les objets où vous compareriez des instances (un list
say)?
D'accord, donc 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 ==
tests de valeur où is
des tests pour voir si elles sont le même objet?
20 réponses
is
retournera True
si deux variables pointent vers le même objet, ==
si les objets visé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 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 vous plaît voir cette question ainsi.
il existe une règle empirique simple pour vous dire quand utiliser ==
ou is
.
-
==
est pour l'égalité de valeur . L'utiliser quand vous voulez savoir si deux objets ont la même valeur. -
is
signifie égalité de référence . L'utiliser quand vous voulez savoir si deux références se rapportent au même objet.
en général, quand vous comparez quelque chose à un type simple, vous vérifiez habituellement pour l'égalité de valeur , donc vous devez utiliser ==
. Par exemple, l'intention de votre exemple est probablement de vérifier si x a une valeur égale à 2 ( ==
), et non si x
se réfère littéralement au même objet que 2.
autre chose à noter: en raison de la façon dont le CPython référence la mise en œuvre 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 que nous nous attendions: a
et b
ont la même valeur, mais sont des entités distinctes. Mais que penser de cela?
>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True
ceci est incompatible avec le résultat antérieur. Ce qui se passe ici? Il s'avère que l'implémentation de référence de Python cache des objets entiers dans l'intervalle -5..256 comme singleton cas 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 pour ne pas utiliser is
: le comportement est laissé à des implémentations quand vous l'utilisez par erreur pour l'égalité des valeurs.
==
détermine si les valeurs sont égales, tandis que is
détermine si elles sont identiques et égales.
ils sont complètement différent . is
vérifie l'identité de l'objet, tandis que ==
vérifie l'égalité (une notion qui dépend des types des deux opérandes).
ce n'est qu'une coïncidence heureuse que " is
" semble fonctionner correctement avec de petits entiers (par exemple 5 == 4+1). C'est parce que CPython optimise le stockage des entiers dans la gamme (-5 à 256) en leur faisant des singletons . Ce comportement est totalement dépendant de la mise en œuvre et n'est pas garanti d'être préservé sous toutes les formes d'opérations de transformation mineures.
par exemple, Python 3.5 fait aussi des chaînes courtes singletons, mais les trancher perturbe ce comportement:
>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False
y a-t-il une différence entre
==
etis
en Python?
Oui, ils ont une différence très importante.
==
: vérifier l'égalité - la sémantique est que les objets équivalents (qui ne sont pas nécessairement le même objet) seront testés comme égaux. Comme la documentation dit :
le les opérateurs <, >, ==, >=, <=, et != comparer les valeurs de deux objets.
is
: vérification d'identité - la sémantique est que l'objet (tel que conservé en mémoire) est l'objet. Encore une fois, la documentation dit :
Les opérateurs
is
etis not
test de l'identité de l'objet:x is y
est vrai si et seulement six
ety
sont le même objet. L'identité de l'objet est déterminée à l'aide de la fonctionid()
.x is not y
donne l'inverse valeur de vérité.
ainsi, le contrôle d'identité est le même que le contrôle de l'égalité des ID des objets. C'est-à-dire,
a is b
est le même que:
id(a) == id(b)
où id
est la fonction intégrée qui renvoie un entier qui "est garanti d'être unique parmi les objets simultanément existants" (voir help(id)
) et où a
et b
sont des objets arbitraires.
Autres Modes D'Emploi
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 officiel de style Python pour la bibliothèque standard mentionne également deux cas d'utilisation pour is
:
les comparaisons avec des lettres uniques comme
None
doivent toujours être faites avecis
ouis not
, jamais les opérateurs d'égalité.aussi, méfiez-vous d'écrire
if x
quand vous voulez vraiment direif x is not None
-- par exemple lors de l'essai d'une variable ou d'un argument par défaut àNone
a été fixée à une autre valeur. L'autre valeur peut avoir un type (tel que en tant que conteneur) qui pourraient être faux dans un contexte booléen!
Déduire l'égalité de l'identité
si is
est vrai, l'égalité peut habituellement être déduite - logiquement, si un objet est lui-même, alors il devrait 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 dire
le comportement par défaut pour la comparaison d'égalité (
==
et!=
) est basé sur l'identité des objets. Par conséquent, la comparaison de l'égalité des instances avec la même identité résulte en égalité, et la comparaison de l'égalité des les cas avec des identités différentes entraînent des inégalités. Un la motivation pour ce comportement par défaut est le désir que tous les objets doit être réflexive (i.e. x est y implique x == y).
et dans un souci de cohérence, recommande:
comparaison d'Égalité doit être réflexive. En d'autres termes, identiques les objets doivent comparer égal:
x is y
impliquex == 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)
le contrapositif est aussi habituellement vrai - si somethings test pas les mêmes, vous pouvez généralement déduire qu'ils ne sont 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 pas égal à lui-même:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
le contrôle d'identité peut être beaucoup plus rapide que le contrôle d'identité égalité (ce qui pourrait exiger 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 la comparaison de l'égalité des listes et des tuples supposera que l'identité des objets est égale (car il s'agit d'un contrôle 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 D'Avertissement:
la question tente d'utiliser is
pour comparer des 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 du code qui s'appuyait sur le fait que les petits entiers (-5 à 256 inclusivement) sont des singletons en Python, au lieu de vérifier l'égalité.
Wow, cela peut conduire à des bugs insidieux. J'avais un code qui vérifiait si a est b, qui fonctionnait comme je le voulais parce que a et b sont généralement de petits nombres. Le bug n'est arrivé qu'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
Il a travaillé dans le développement. Il peut avoir passé quelques unittests.
et il a fonctionné dans la production - jusqu'à ce que le code vérifié pour un entier plus grand que 256, à quel point il a échoué dans la production.
il s'agit d'un échec de production qui aurait pu être détecté lors d'une révision de code ou peut-être avec un vérificateur de style.
permettez-moi de souligner: ne pas utiliser is
pour comparer des entiers.
https://docs.python.org/library/stdtypes.html#comparisons
is
tests d'identité
==
critères d'égalité
chaque (petite) valeur entière est mappée à une seule valeur, donc chaque 3 est identique et égale. Il s'agit d'un détail de mise en œuvre, ne fait pas partie de la spécification de la langue bien que
Quelle est la différence entre is
et ==
?
==
et is
sont différentes de comparaison! Comme d'autres l'ont déjà dit:
-
==
compare les valeurs des objets. -
is
compare les références des objets.
dans les noms de Python se réfèrent à des objets, par exemple dans ce cas value1
et value2
se réfèrent à un int
instance de stockage de la valeur 1000
:
value1 = 1000
value2 = value1
parce que value2
fait référence au même objet is
et ==
donnera True
:
>>> value1 == value2
True
>>> value1 is value2
True
dans l'exemple suivant les noms value1
et value2
se réfèrent à des instances différentes int
, même si les deux stockent le même entier:
>>> value1 = 1000
>>> value2 = 1000
parce que la même valeur (entier) est stockée ==
sera True
, c'est pourquoi il est souvent appelé"comparaison de valeur". Cependant is
retournera False
parce que ce sont des objets différents:
>>> value1 == value2
True
>>> value1 is value2
False
quand utiliser qui?
généralement is
est un beaucoup plus rapide comparaison. C'est pourquoi CPython cache (ou peut-être réutilise serait le meilleur terme) Certains objets comme de petits entiers, quelques chaînes, etc. Mais cela devrait être traité comme détail de mise en œuvre qui pourrait (même si peu probable) changer à tout moment sans avertissement.
Vous devriez utiliser uniquement is
si vous:
- je veux vérifier si deux objets sont vraiment le même objet (pas seulement la même "valeur"). Un exemple peut être si vous utilisez un objet singleton comme constante.
-
comparez une valeur à une Python constante . Les constantes en Python sont:
-
None
-
True
1 -
False
1 -
NotImplemented
-
Ellipsis
-
__debug__
- classes (par exemple
int is int
ouint 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
du module NumPy)
-
In tous les autres cas, vous devez utiliser ==
pour vérifier l'égalité.
puis-je personnaliser le comportement?
il y a un aspect de ==
qui n'a pas été mentionné déjà dans les autres réponses: il fait partie de pythons" modèle de données " . Cela signifie que son comportement peut être personnalisé en utilisant la méthode __eq__
. 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)))
ce n'est qu'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 mise en œuvre de __eq__
peut être trouvé dans la classe ou le super-classes) __eq__
utilise 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 en fait important d'implémenter __eq__
si vous voulez" plus " que de la simple comparaison de référence pour des classes personnalisées!
sur le d'autre part vous ne pouvez pas personnaliser is
contrôles. Il comparera toujours juste si vous avez la même référence.
est-ce que ces comparaisons retourneront toujours un booléen?
parce que __eq__
peut être ré-implémenté ou annulé, il n'est pas limité à retourner True
ou False
. Il pourrait retourner n'importe quoi (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 retourneront toujours True
ou False
!
1 comme Aaron Hall l'a mentionné dans les commentaires:
généralement, vous ne devriez pas faire de is True
ou is False
vérifications parce qu'on utilise normalement ces "vérifications" dans un contexte qui convertit implicitement la condition en booléen (par exemple dans une instruction if
). Ainsi, faire la is True
comparaison et la distribution booléenne implicite fait plus de travail que juste faire la distribution booléenne - et vous vous limitez aux booléens (qui n'est pas considéré pythonique).
comme PEP8 mentionne:
ne comparez pas les valeurs booléennes à
True
ouFalse
par==
.Yes: if greeting: No: if greeting == True: Worse: if greeting is True:
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 contrôler le comportement de comparaison des valeurs d'objet en définissant une méthode __cmp__
ou une riche comparaison méthode comme __eq__
.
Avoir un coup d'oeil à Débordement de Pile question Python "est" l'opérateur se comporte de manière inattendue avec des entiers .
ce qui se résume le plus souvent à cela " is
" vérifie s'ils sont le même objet, pas seulement égaux l'un à l'autre (les nombres en dessous de 256 sont un cas spécial).
comme L'a dit John Feminella, la plupart du temps vous utiliserez == et != parce que 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 Qu'aucun n'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 pythonique est d'utiliser foo is None
.
si vous faites introspection ou de mucking autour de la collecte des ordures ou de vérifier si votre gadget d'entrainement de chaîne sur mesure fonctionne ou semblable, alors vous avez probablement un cas d'utilisation pour foo
est bar
.
vrai et faux sont aussi (maintenant) singletons, mais il n'y a pas de cas d'utilisation pour foo == True
et aucun cas d'utilisation pour foo is True
.
en Fait, je voulais ajouter un commentaire, mais ne pouvait pas embellir facilement, d'où l'ajout d'une réponse, s'il vous plaît ne considérez pas cela comme une réponse.
C'est ce que j'ai fait pour comprendre --
exécuter suivants un par un et de comprendre de sortie sur chaque étape
a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b
la plupart d'entre eux ont déjà répondu au point. Tout comme une note supplémentaire (basée sur ma compréhension et l'expérimentation, mais pas à partir d'une source documentée), la déclaration
= = si les objets auxquels se réfèrent les variables sont égaux
les réponses ci-dessus doivent être lues comme suit:
= = si les objets auxquels se réfèrent les variables sont égaux et les objets appartenant au même type /classe
. Je suis arrivé à cette conclusion sur la base du test suivant:
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 tuple sont les mêmes mais le type/classe sont différents.
en bref, 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 pas.
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
l'opérateur ==
compare les valeurs des opérandes et vérifie l'égalité des valeurs. Tandis que l'opérateur is
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 le 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
en gros, is
peut être considéré comme un raccourci pour id(a) == id(b)
. Cependant, au-Delà de cela, il y a des bizarreries de l'environnement d'exécution que compliquer les choses. Cordes courtes et les petits entiers retourneront True
par rapport à is
, en raison de la machine Python essayant d'utiliser moins de mémoire pour les objets identiques.
a = 'python'
b = 'python'
print(a == b) # true
print(a is b) # true
Python différence entre l'est et du signe égal(==)
l'opérateur is peut sembler identique à l'opérateur d'égalité mais ils ne sont pas les mêmes.
L'est vérifie si les deux variables pointent vers le même objet alors que le signe == vérifie si les valeurs des deux variables sont les mêmes.
Donc, si l'opérateur retourne True alors l'égalité est certainement Vrai, mais le contraire peut ou ne peut pas être Vrai.
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.
"==" compare les valeurs
" is "compare les objets sous-jacents
# this pgm is to show you the diff b/n == and is
# a==b and a is b
# == compares values
# is compares references i.e compares wether two variables refer to same object(memory)
a=10
b=10
print(a==b) # returns True as a,b have same value 10
print(a is b)
# returns True,
# we usually falsey assume that a =10 a new object . b=10 a new obj created
# but actually when b=10 ,nothing but b is pointed to 10 until value of a or b is changed from 10
a=[1]
b=[1]
print(a==b)
#returns True as a,b have a list element 1
print(a is b)
#returns False because here two different objs are created when initiated with lists
o1 is o2 = > compare si o1 et o2 indiquent tous deux le même emplacement physique dans la mémoire (en d'autres termes s'ils sont le même objet)
o1 == o2 = > ici, python appelle la méthode __cmp __(o2) de o1, qui idéalement devrait comparer la valeur et retourner vrai ou faux. (En d'autres termes, il compare la valeur)
JAVA Pour les gens:
-
en Java, pour déterminer si deux variables de chaîne font référence à la même emplacement de la mémoire physique en utilisant str1 = = str2 . (appelé objet identité, et il est écrit en Python comme str1 est str2 ).
-
pour comparer les valeurs des chaînes en Java, usestr1.égale (str2) ; dans Python, utiliser str1 = = str2 .
exemple:
class A():
...: def __init__(self,a):
...: self.a = a
...: def __repr__(self):
...: return str(self.a)
...: def __cmp__(self, value):
...: print self.a
...: print value.a
...: return cmp(self.a, value.a)
sortie Python Shell:
o = A (2) o1 = o
o = = o1 Deux Deux Vrai
O est o1 Vrai
s1 = A(2)
O est o1 Faux
comme les autres personnes dans ce post répondre à la question dans les détails, je souligner principalement la comparaison entre is
et ==
pour les cordes qui peuvent donner des résultats différents et je voudrais exhorter les programmeurs à les utiliser avec soin.
pour la comparaison de chaîne, assurez-vous d'utiliser ==
au lieu de is
:
str = 'hello'
if (str is 'hello'):
print ('str is hello')
if (str == 'hello'):
print ('str == hello')
:
str is hello
str == hello
mais dans l'exemple ci-dessous ==
et is
obtiendra 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')
:
str == hello sam
Conclusion:
utiliser is
soigneusement comparer entre les cordes
Oui, il y a une différence entre les deux.
- '==' : compare object by value.
-
'dans : compare objet par référence.
a = [1,2,3] b = a # both pointing to same object (memory location) a == b: True a in b: True #because a and b are pointing to same object
examinons maintenant ce cas:
a = [1,2,3]
b = list(a) # creating copy of object a
a == b:
True # as values are same
a in b:
False # because they are pointing to different object.
bien que toutes les réponses qui reposent sur la mise en œuvre de la comparaison des pointeurs d'objection par rapport à la comparaison des valeurs soient probablement correctes, il y a une raison syntaxique plus profonde pour utiliser is
pour déterminer si une valeur variable est None
(dans la logique booléenne souvent représentée par NULL
).
Dans la base de données relationnelle et d'autres systèmes logiques, NULL
implique que la valeur réelle est "inconnu". Ainsi, l'expression logique xx == NULL
doit toujours évaluer à NULL
lui-même , car il est impossible de savoir si xx
, quelle que soit sa valeur, est la même que la valeur inconnue. Dans les langages de programmation qui adhèrent plus strictement aux règles de la logique booléenne, xx == NULL
(ou Pythoniquement xx == None
) évalue correctement à NULL
, et des moyens alternatifs doivent être fournis pour déterminer si une valeur variable est NULL
. Python est une valeur aberrante à cet égard, en raison de la nature unitaire de la référence objet à None
. Mais par souci de clarté et d'exactitude logique, l'utilisation de l'opérateur de comparaison Python is
me semble beaucoup plus pratique.