A common pitfall is confusing the equality comparison operators is and ==.
a == b compares the value of a and b.
a is b will compare the identities of a and b.
To illustrate:
a = 'Python is fun!'
b = 'Python is fun!'
a == b # returns True
a is b # returns False
a = [1, 2, 3, 4, 5]
b = a # b references a
a == b # True
a is b # True
b = a[:] # b now references a copy of a
a == b # True
a is b # False [!!]
Basically, is can be thought of as shorthand for id(a) == id(b).
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 = 'short'
b = 'short'
c = 5
d = 5
a is b # True
c is d # True
But longer strings and larger integers will be stored separately.
a = 'not so short'
b = 'not so short'
c = 1000
d = 1000
a is b # False
c is d # False
You should use is to test for None:
if myvar is not None:
# not None
pass
if myvar is None:
# None
pass
A use of is is to test for a “sentinel” (i.e. a unique object).
sentinel = object()
def myfunc(var=sentinel):
if var is sentinel:
# value wasn’t provided
pass
else:
# value was provided
pass