You Can't Handle the Truth!
I got a chance to review some other people’s Python code recently, and there’s one comment I almost always have to give, which is:
if x is not Noneare not the same!
if not xand
if x is Noneare also quite different, obviously.
This usually happens when someone assigns
None to a variable (say,
x) as a sentinel value, and then
x may or may not be assigned to. The test is designed to check whether or not
x was assigned to, or not.
When you do
if x is None, you call the operator
is, which checks the identity of
None is a singleton in Python and all
None values are also the exact same instance. When you say
if x, something different happens. if expects a boolean, and assuming
x is not a boolean, Python automatically calls
__nonzero__ method. i.e.,
if x is actually executed as
if x.__nonzero__ (or
__nonzero__ is pretty poorly named1, but it’s a method that evaluated a class as a boolean value. It’s one of Python’s Magic Methods. The confusing thing is, that
False, so if x is None,
if x works as you expect it to. However, there are other values that are evaluated as
False. The most prominent example is an empty list.
False as well. Usually, an empty list has a meaning that is different to
None; None means no value while an empty list means zero values. Semantically, they are different. I guess people are just unaware of the semantic difference between the two ways to write the condition.
Here are some useful snippets to demonstrate:
Testing an Empty List
Testing a Normal Value
Testing a Custom Class
Fortunately, the folks working on Python had the sense to change this to
__bool__in Python 3.x! ↩︎
Follow me on Twitter , Facebook or Google+