Being Nothingness: Comparing to None in Python
by January 27, 2014

Filed under: Performance Monitoring

AppNeta no longer blogs on DevOps topics like this one.

Feel free to enjoy it, and check out what we can do for monitoring end user experience of the apps you use to drive your business at

The “is None” Idiom

Consider these two snippets from PEP-0008:

“Comparisons to singletons like None should always be done with is or is not, never the equality operators.

Also, beware of writing if x when you really mean if x is not None — e.g. when testing whether a variable or argument that defaults to None was set to some other value. The other value might have a type (such as a container) that could be false in a boolean context!”

Later in that document, we see:

“Don’t compare boolean values to True or False using ==.

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:

So, singletons like None are supposed to be compared using “is” and “is not”. But the language’s other two singletons, True and False, are supposed to be used differently. Are there other singletons? Or more importantly, are there other singletons like None, which we should compare with “is” and “is not”.

The suggestion to write “x is None” instead of “x == None” is quite old now. The very first draft of PEP-0290 recommends converting x == None and x != None into the is and is not alternatives. At about the same time, PEP-0008 changed to include the selections above. These changes were in 2002, when Python 2.2 was current and 2.3 is under development. So for over a decade, the Python community has preferred all comparisons to None, to be done with the is operator. The formulation “x is None” is now considered idiomatic Python.

That That “is” Costs


But this idiom has a cost. Very rarely does a programmer actually want to use the “is” operator. Identical objects are not guaranteed to compare True under “is” — not even identical strings. These operators have a very narrow utility. When beginners try to employ it, the results are not intuitive. Even to veteran programmers, the results of “is” comparisons can be surprising.

>>> 999 is 999
>>> x = 999 ; y = 999
>>> x is y
>>> z = 999
>>> x is z

Confusing, right? This behavior is also implementation-specific: in general, integers are not singletons like None, and two integers with the same value will be represented by different objects in memory.

The “is not” operator introduces another semantic confusion. It’s the only Python operator that is spelled with two words, and what’s more, both those words are also operators when encountered on their own. This leads to a separate confusion, documented around the web:

>>> False is not None
>>> False is (not None)

Though this snippet may appear to describe something about the associativity of the “is” or “not” operator, it’s actually something different. In the first case, the expression uses the “is not” operator; in the second case, the expression uses the “is” and “not” operators. It’s unlikely that too many programmers will encounter bugs based on this distinction, but it’s a distinction that may not be obvious.

But Why?

One of the arguments in favor of using “is None” has been that an object might override “__eq__” such that it compares as equal to None. I find it strange that this would argue in favor of using the “is” idiom. Truthiness and duck typing are well-established concepts in idiomatic Python. Truthiness is documented in the  “Truth Value Testing” section of the library reference, and duck typing is touted as a language feature. Testing with an identity operator goes against both of these trends, even if it is just for the case of None.

In PEP-0290, the logic offered is that an “is” test is slightly faster in the case of built-in objects, and much faster in the event of objects that have a custom “__eq__” method. In other words, this idiom has entered the language largely as an optimization pattern.

>>> min(timeit.Timer('x is None', setup="x = 1").repeat(10, 1000000))
>>> min(timeit.Timer('x == None', setup="x = 1").repeat(10, 1000000))

Okay, I guess that will help.