Explain Codes LogoExplain Codes Logo

Python None comparison: should I use "is" or ==?

python
singleton
best-practices
functions
Nikita BarsukovbyNikita Barsukov·Mar 3, 2025
TLDR

When comparing to None, use the is operator. This is operator checks for identity, which ensures the variable is specifically None. Utilizing == could be precarious due to potential custom equality methods.

Here's a quick example:

if my_mystery_variable is None: print("Sherlock Holmes, the case is solved! It's None!")

Dive deeper: the details of "is" vs "=="

The clarity of "is" for None checks

The unpredictable nature of "=="

The time bomb of custom classes

When it comes to Python and the mysterious case of None, the is operator is your trusty companion. This is because None is a singleton - there is only one true None like Voldemort's one true heir. Using is is like checking the prophecy to see if it's indeed about 'None'. It's quick, it's precise, and it never lies.

In contrast, == is like asking, "Would two prophecies mean the same thing?" Even though they might foretell the same outcome, they're still different pieces of ancient paper. In Python, this equality can be tailored in custom classes, leading to unpredictable behavior when == could return True even when you're dealing with He-Who-Must-Not-Be-None.

Element of surprise! Exploding with "is"

if the_prophecy is None: # The prophecy is yet to be written. Let's not get ahead of ourselves! print("The Oracle is taking a break!")

Remember, in Python, None, and some small integers and strings are singleton_interned. This means there's one true 'None' memory-wise, making it both safe and efficient to compare with is.

Love potions gone wrong: why "=="

class Amortentia: def __eq__(self, other): return True if other is None else False love_potion = Amortentia() if love_potion == None: # The love potion heard 'None' and thought it call. print("Unrequited love strikes again!")

Use == wisely or you might end up with something thinking it's None when it isn't. PEP 8 also plays matchmaker by advising us against comparing None with ==.

Don't get "is" in a twist

Integer illusion

Mutables madness

Custom singletons

Just like the Room of Requirement, Python's mighty is has its limitations. is might lead you astray with non-singleton mutable objects or integers not in the Hogwarts-approved -5 to 256 range. This is due to Python's wizardry, called interning, where it recycles memory addresses for certain objects.

Integers are not what they seem!

Unlike our steadfast friend None, the is operator can give a false sense of identity when comparing unique integers:

magic_number = 257 another_number = 257 print(magic_number is another_number) # Much to the Basilisk's surprise, this may print False!

For mutable objects, checking for identity rather than value can also lead to confusion.

There can only be one! (Custom singletons)

For your custom singletons, you can use is just like you would with None:

class SingletonCalendar(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class WeasleyFamilyCalendar(metaclass=SingletonCalendar): pass weasley_calendar = WeasleyFamilyCalendar() another_calendar = WeasleyFamilyCalendar() if weasley_calendar is another_calendar: print("All's good. We're not double-booking Quidditch!")