¿Hay alguna diferencia entre & # 8220; == & # 8221; y & # 8220; es & # 8221 ;?
Pregunta
Mi Google-fu me ha fallado.
En Python, ¿son equivalentes las siguientes dos pruebas de igualdad?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
¿Esto es válido para los objetos en los que compararía instancias (una list
say)?
Bien, entonces este tipo de respuestas a mi pregunta:
L = []
L.append(1)
if L == [1]:
print 'Yay!'
# Holds true, but...
if L is [1]:
print 'Yay!'
# Doesn't.
Entonces ==
prueba el valor donde es
se comprueba para ver si son el mismo objeto.
Solución
is
devolverá True
si dos variables apuntan al mismo objeto, ==
si los objetos a los que hacen referencia las variables son iguales.
>>> 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
En su caso, la segunda prueba solo funciona porque Python almacena en caché pequeños objetos enteros, que es un detalle de implementación. Para enteros más grandes, esto no funciona:
>>> 1000 is 10**3
False
>>> 1000 == 10**3
True
Lo mismo se aplica a los literales de cadena:
>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True
Consulte esta pregunta ??a > también.
Otros consejos
Hay una simple regla de oro para decirle cuándo usar ==
o es
.
-
==
es para igualdad de valores . Úselo cuando desee saber si dos objetos tienen el mismo valor. -
is
es para igualdad de referencia . Úselo cuando desee saber si dos referencias se refieren al mismo objeto.
En general, cuando está comparando algo con un tipo simple, por lo general está comprobando la igualdad de valores , por lo que debe usar ==
. Por ejemplo, la intención de su ejemplo es probablemente comprobar si x tiene un valor igual a 2 ( ==
), no si x
se refiere literalmente al mismo objeto que 2.
Otra cosa a tener en cuenta: debido a la forma en que funciona la implementación de referencia de CPython, obtendrá resultados inesperados e inconsistentes si por error utiliza es
para comparar la igualdad de referencia en enteros:
>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False
Eso es más o menos lo que esperábamos: a
y b
tienen el mismo valor, pero son entidades distintas. Pero ¿qué pasa con esto?
>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True
Esto es inconsistente con el resultado anterior. ¿Que está pasando aqui? Resulta que la implementación de referencia de Python almacena en caché objetos enteros en el rango -5..256 como instancias singleton por razones de rendimiento. Aquí hay un ejemplo que demuestra esto:
>>> 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
Esta es otra razón obvia para no usar :
: el comportamiento se deja en las implementaciones cuando se usa erróneamente para la igualdad de valores.
==
determina si los valores son iguales, mientras que is
determina si son exactamente el mismo objeto e iguales.
Is there a difference between
==
andis
in Python?
Yes, they have a very important difference.
==
: check for equality - the semantics are that equivalent objects (that aren't necessarily the same object) will test as equal. As the documentation says:
The operators <, >, ==, >=, <=, and != compare the values of two objects.
is
: check for identity - the semantics are that the object (as held in memory) is the object. Again, the documentation says:
The operators
is
andis not
test for object identity:x is y
is true if and only ifx
andy
are the same object. Object identity is determined using theid()
function.x is not y
yields the inverse truth value.
Thus, the check for identity is the same as checking for the equality of the IDs of the objects. That is,
a is b
is the same as:
id(a) == id(b)
where id
is the builtin function that returns an integer that "is guaranteed to be unique among simultaneously existing objects" (see help(id)
) and where a
and b
are any arbitrary objects.
Other Usage Directions
You should use these comparisons for their semantics. Use is
to check identity and ==
to check equality.
PEP 8, the official Python style guide for the standard library also mentions two use-cases for is
:
Comparisons to singletons like
None
should always be done withis
oris not
, never the equality operators.Also, beware of writing
if x
when you really meanif x is not None
-- e.g. when testing whether a variable or argument that defaults toNone
was set to some other value. The other value might have a type (such as a container) that could be false in a boolean context!
Inferring equality from identity
If is
is true, equality can usually be inferred - logically, if an object is itself, then it should test as equivalent to itself.
In most cases this logic is true, but it relies on the implementation of the __eq__
special method. As the docs say,
The default behavior for equality comparison (
==
and!=
) is based on the identity of the objects. Hence, equality comparison of instances with the same identity results in equality, and equality comparison of instances with different identities results in inequality. A motivation for this default behavior is the desire that all objects should be reflexive (i.e. x is y implies x == y).
and in the interests of consistency, recommends:
Equality comparison should be reflexive. In other words, identical objects should compare equal:
x is y
impliesx == y
We can see that this is the default behavior for custom objects:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
The contrapositive is also usually true - if somethings test as not equal, you can usually infer that they are not the same object.
Since tests for equality can be customized, this inference does not always hold true for all types.
An exception
A notable exception is nan
- it always tests as not equal to itself:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
Checking for identity can be much a much quicker check than checking for equality (which might require recursively checking members).
But it cannot be substituted for equality where you may find more than one object as equivalent.
Note that comparing equality of lists and tuples will assume that identity of objects are equal (because this is a fast check). This can create contradictions if the logic is inconsistent - as it is for nan
:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
A Cautionary Tale:
The question is attempting to use is
to compare integers. You shouldn't assume that an instance of an integer is the same instance as one obtained by another reference. This story explains why.
A commenter had code that relied on the fact that small integers (-5 to 256 inclusive) are singletons in Python, instead of checking for equality.
Wow, this can lead to some insidious bugs. I had some code that checked if a is b, which worked as I wanted because a and b are typically small numbers. The bug only happened today, after six months in production, because a and b were finally large enough to not be cached. – gwg
It worked in development. It may have passed some unittests.
And it worked in production - until the code checked for an integer larger than 256, at which point it failed in production.
This is a production failure that could have been caught in code review or possibly with a style-checker.
Let me emphasize: do not use is
to compare integers.
What's the difference between is
and ==
?
==
and is
are different comparison! As others already said:
==
compares the values of the objects.is
compares the references of the objects.
In Python names refer to objects, for example in this case value1
and value2
refer to an int
instance storing the value 1000
:
value1 = 1000
value2 = value1
Because value2
refers to the same object is
and ==
will give True
:
>>> value1 == value2
True
>>> value1 is value2
True
In the following example the names value1
and value2
refer to different int
instances, even if both store the same integer:
>>> value1 = 1000
>>> value2 = 1000
Because the same value (integer) is stored ==
will be True
, that's why it's often called "value comparison". However is
will return False
because these are different objects:
>>> value1 == value2
True
>>> value1 is value2
False
When to use which?
Generally is
is a much faster comparison. That's why CPython caches (or maybe reuses would be the better term) certain objects like small integers, some strings, etc. But this should be treated as implementation detail that could (even if unlikely) change at any point without warning.
You should only use is
if you:
- want to check if two objects are really the same object (not just the same "value"). One example can be if you use a singleton object as constant.
want to compare a value to a Python constant. The constants in Python are:
None
True
1False
1NotImplemented
Ellipsis
__debug__
- classes (for example
int is int
orint is float
) - there could be additional constants in built-in modules or 3rd party modules. For example
np.ma.masked
from the NumPy module)
In every other case you should use ==
to check for equality.
Can I customize the behavior?
There is some aspect to ==
that hasn't been mentioned already in the other answers: It's part of Pythons "Data model". That means its behavior can be customized using the __eq__
method. For example:
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)))
This is just an artificial example to illustrate that the method is really called:
>>> MyClass(10) == MyClass(10)
__eq__ method called
True
Note that by default (if no other implementation of __eq__
can be found in the class or the superclasses) __eq__
uses is
:
class AClass(object):
def __init__(self, value):
self._value = value
>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a
So it's actually important to implement __eq__
if you want "more" than just reference-comparison for custom classes!
On the other hand you cannot customize is
checks. It will always compare just if you have the same reference.
Will these comparisons always return a boolean?
Because __eq__
can be re-implemented or overridden, it's not limited to return True
or False
. It could return anything (but in most cases it should return a boolean!).
For example with NumPy arrays the ==
will return an array:
>>> import numpy as np
>>> np.arange(10) == 2
array([False, False, True, False, False, False, False, False, False, False], dtype=bool)
But is
checks will always return True
or False
!
1 As Aaron Hall mentioned in the comments:
Generally you shouldn't do any is True
or is False
checks because one normally uses these "checks" in a context that implicitly converts the condition to a boolean (for example in an if
statement). So doing the is True
comparison and the implicit boolean cast is doing more work than just doing the boolean cast - and you limit yourself to booleans (which isn't considered pythonic).
Like PEP8 mentions:
Don't compare boolean values to
True
orFalse
using==
.Yes: if greeting: No: if greeting == True: Worse: if greeting is True:
They are completely different. is
checks for object identity, while ==
checks for equality (a notion that depends on the two operands' types).
It is only a lucky coincidence that "is
" seems to work correctly with small integers (e.g. 5 == 4+1). That is because CPython optimizes the storage of integers in the range (-5 to 256) by making them singletons. This behavior is totally implementation-dependent and not guaranteed to be preserved under all manner of minor transformative operations.
For example, Python 3.5 also makes short strings singletons, but slicing them disrupts this behavior:
>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False
https://docs.python.org/library/stdtypes.html#comparisons
is
tests for identity
==
tests for equality
Each (small) integer value is mapped to a single value, so every 3 is identical and equal. This is an implementation detail, not part of the language spec though
Your answer is correct. The is
operator compares the identity of two objects. The ==
operator compares the values of two objects.
An object's identity never changes once it has been created; you may think of it as the object's address in memory.
You can control comparison behaviour of object values by defining a __cmp__
method or a rich comparison method like __eq__
.
The ==
operator compares the values of both the operands and checks for value equality. Whereas is
operator checks whether both the operands refer to the same object or not.
a = [1,2,3,4]
b = a
print(a == b) # true
print(a is b) # true
But if we do
b = a[:] # b now references a copy of a
print(a == b) # true
print(a is b) # false
print(a is not b) # true
Basically, is
can be thought of as shorthand for id(a) == id(b)
. However, Beyond this, there are quirks of the run-time environment that further complicate things. Short strings and small integers will return True
when compared with is
, due to the Python machine attempting to use less memory for identical objects.
a = 'python'
b = 'python'
print(a == b) # true
print(a is b) # true
Have a look at Stack Overflow question Python's “is” operator behaves unexpectedly with integers.
What it mostly boils down to is that "is
" checks to see if they are the same object, not just equal to each other (the numbers below 256 are a special case).
As John Feminella said, most of the time you will use == and != because your objective is to compare values. I'd just like to categorise what you would do the rest of the time:
There is one and only one instance of NoneType i.e. None is a singleton. Consequently foo == None
and foo is None
mean the same. However the is
test is faster and the Pythonic convention is to use foo is None
.
If you are doing some introspection or mucking about with garbage collection or checking whether your custom-built string interning gadget is working or suchlike, then you probably have a use-case for foo
is bar
.
True and False are also (now) singletons, but there is no use-case for foo == True
and no use case for foo is True
.
Most of them already answered to the point. Just as an additional note (based on my understanding and experimenting but not from a documented source), the statement
== if the objects referred to by the variables are equal
from above answers should be read as
== if the objects referred to by the variables are equal and objects belonging to the same type/class
. I arrived at this conclusion based on the below test:
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)
Here the contents of the list and tuple are same but the type/class are different.
In a nutshell, is
checks whether two references point to the same object or not.==
checks whether two objects have the same value or not.
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
Actually I wanted to add this as a comment but could not beautify it easily hence adding as an answer, please do not consider this as an answer.
This is what I did to understand --
execute following one by one and understand output on every step
a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b
As the other people in this post answer the question in details, I would emphasize mainly the comparison between is
and ==
for strings which can give different results and I would urge programmers to carefully use them.
For string comparison, make sure to use ==
instead of is
:
str = 'hello'
if (str is 'hello'):
print ('str is hello')
if (str == 'hello'):
print ('str == hello')
Out:
str is hello
str == hello
But in the below example ==
and is
will get different results:
str = 'hello sam'
if (str is 'hello sam'):
print ('str is hello sam')
if (str == 'hello sam'):
print ('str == hello sam')
Out:
str == hello sam
Conclusion:
Use is
carefully to compare between strings
Python difference between is and equals(==)
The is operator may seem like the same as the equality operator but they are not same.
The is checks if both the variables point to the same object whereas the == sign checks if the values for the two variables are the same.
So if the is operator returns True then the equality is definitely True, but the opposite may or may not be True.
Here is an example to demonstrate the similarity and the difference.
>>> 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.
"==" compares values
"is" compares underlying objects
# 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 => compares if o1 and o2 both points to same physical location in memory (in other words if they are same object)
o1 == o2 => here python call the o1's __cmp __(o2) method, which ideally should compares the value and return True or False. (In other words it compares value)
For JAVA people:
In Java, to determine whether two string variables reference the same physical memory location by using str1 == str2. (called object identity, and it is written in Python as str1 is str2).
To compare string values in Java, usestr1.equals(str2); in Python, use str1 == str2.
Example:
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)
Python Shell output:
o = A(2) o1 = o
o == o1 2 2 True
o is o1 True
o1 = A(2)
o is o1 False
If you compare it with JavaScript (however, not recommended to compare one language vs another):
- Use
is
for strict comparison. Javascript equivalent (===
) - Use
==
for equality comparison.
While all these answers that rely on the implementation of objection pointer comparison vs value comparison are likely correct, there is a deeper syntactical reason for using is
to determine if a variable value is None
(in boolean logic often represented as NULL
).
In relational database and other logic systems, NULL
implies that the actual value is "unknown". Thus the logical expression xx == NULL
must always evaluate to NULL
itself, as it is impossible to ever know if xx
, whatever value it may have, is the same as the unknown value. In programming languages that adhere more strictly to the rules of boolean logic, xx == NULL
(or Pythonically xx == None
) correctly evaluates to NULL
, and alternative means must be provided to determine if a variable value is NULL
. Python is an outlier in this regard, due to the unitary nature of the object reference to None
. But for clarity and logical correctness, using the Python is
comparison operator seems to me much sounder practice.
Yes, there is difference between both.
- '==' : compares object by value.
'in' : compares object by reference.
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
Now let's consider this case:
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.