Python None comparison: should I use is or ==?
Summary:
Use is
when you want to check against an object's identity (e.g. checking to see if var
is None
). Use ==
when you want to check equality (e.g. Is var
equal to 3
?).
Explanation:
You can have custom classes where my_var == None
will return True
e.g:
class Negator(object):
def __eq__(self,other):
return not other
thing = Negator()
print thing == None #True
print thing is None #False
is
checks for object identity. There is only 1 object None
, so when you do my_var is None
, you're checking whether they actually are the same object (not just equivalent objects)
In other words, ==
is a check for equivalence (which is defined from object to object) whereas is
checks for object identity:
lst = [1,2,3]
lst == lst[:] # This is True since the lists are "equivalent"
lst is lst[:] # This is False since they're actually different objects
What is the difference between is None and == None
The answer is explained here.
To quote:
A class is free to implement
comparison any way it chooses, and it
can choose to make comparison against
None mean something (which actually
makes sense; if someone told you to
implement the None object from
scratch, how else would you get it to
compare True against itself?).
Practically-speaking, there is not much difference since custom comparison operators are rare. But you should use is None
as a general rule.
Should I just use `==` to compare to `(None, None)` tuple?
You should use ==
, but indeed it's not "obvious" that using is
would fail.
For example
def foo():
return (1, 2)
print(foo() is foo())
MAY actually return True
(it does in CPython, not sure about other implementations).
Tuples are NOT to be considered entities, but values. Identity on values shouldn't be used as it may match or not (like happens for example for strings or numbers).
If in the code above you use [1, 2]
instead of (1, 2)
then it's guaranteed that is
will return False
because lists are entities, not values, and identity can be used in predictable ways.
Should I compare with None explicitly
It depends on the values your variable may take and the expectations your code has. If your variable may take on other falsey values, then yes, the difference between None
and, say, []
may be significant and you need to explicitly check for is None
.
But not always. What if your value is a falsey []
, and you're writing an if foo:
to decide whether you have a value that needs processing? Well, an empty list might not need processing either, since it's empty. So both None
and []
can be treated the same. In this case you'd need to explicitly check for is None
and and empty list, in which case if foo:
already encapsulates both very succinctly.
In your case, if the variable can be either None
or a Thread
, there's no difference whether you add is not None
or not, it will behave identically in both cases. So why make it more verbose than it needs to be?
There's no one rule that fits all situations.
identity versus equality for None in Python
The reason people use is
is because there is no advantage to using ==
. It is possible to write objects that compare equal to None
, but it is uncommon.
class A(object):
def __eq__(self, other):
return True
print A() == None
Output:
True
The is
operator is also faster, but I don't consider this fact important.
Is there a difference between == and is ?
is
will return True
if two variables point to the same object (in memory), ==
if the objects referred to by the variables are equal.
>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
>>> b == a
True
# Make a new copy of list `a` via the slice operator,
# and assign it to variable `b`
>>> b = a[:]
>>> b is a
False
>>> b == a
True
In your case, the second test only works because Python caches small integer objects, which is an implementation detail. For larger integers, this does not work:
>>> 1000 is 10**3
False
>>> 1000 == 10**3
True
The same holds true for string literals:
>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True
Please see this question as well.
Comparing None with built-in types using arithmetic operators?
The only meaningful comparison you can really use with None
is if obj is None:
(or if obj is not None:
).
Comparison between different types has been removed from Python 3 for good reasons - they were a common source of errors and lead to confusion. For example
>>> "3" < 4
False
In Python 3, you get a TypeError
when comparing values of different types like str
vs. int
or anything vs. None
.
>>> None < 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < int()
(I mean "comparing" in the sense of trying to determine which of two values is larger/smaller. Comparison for equality is OK - it will always return False
if two object are of different types.)
I haven't found a reference in the docs for this, but in Learning Python, 4th edition, Mark Lutz writes on page 204:
[...] Comparisons of differently typed objects (e.g., a string and a
list) work — the language defines a fixed ordering among different
types, which is deterministic, if not aesthetically pleasing. That is,
the ordering is based on the names of the types involved: all integers
are less than all strings, for example, because"int"
is less than
"str"
.
Related Topics
Problem Running Python from Crontab - "Invalid Python Installation"
Problems Adding Path and Calling External Program from Python
Python Multiprocessing + Subprocess Issues
Set Bash Variable from Python Script
Unicodedecodeerror Reading Binary Input
What Is the Correct Way to Include Localisation in Python Packages
Python Script Not Working via Cron
Why Does Loading the Libc Shared Library Have "'Libraryloader' Object Is Not Callable" Error
After Conda Update, Python Kernel Crashes When Matplotlib Is Used
Extracting Extension from Filename in Python
How to Get an Absolute File Path in Python
Best Way to Replace Multiple Characters in a String