Python: Booleans and None
You Can't Handle the Truth!
I would still love to hear your feedback in the comments below. Enjoy!
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
andif x is not None
are not the same!
corollary:if not x
andif x is None
are 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 x
. 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 x
’s __nonzero__
method. i.e., if x
is actually executed as if x.__nonzero__
(or bool(x)
). __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 bool(None)
returns 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. bool([])
returns 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 None
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 and Facebook