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
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__
int is int
or int is float
)np.ma.masked
from the NumPy module)In every other case you should use ==
to check for equality.
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.
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: