Course Content
Python Essentials for AI Engineer
6 sections · 48 lessons
What is the difference between == and is?
What you need to know
Value vs identity
1a = [1, 2, 3]2b = [1, 2, 3]3c = a4print(a == b, a is b) # True False -> equal contents, two objects5print(a is c) # True -> c is another name for a6print(id(a) == id(c)) # True== can be customised by a class (it calls __eq__), so "equal" means whatever the class says. is cannot be overridden; it is a pure identity check, and it is very fast.
Why is on numbers and strings is unreliable
CPython pre-creates the integers from -5 to 256 and reuses them, and it reuses ("interns") some strings. So is can return True by accident:
1x = 256; y = int("256")2print(x is y) # True -> both are the cached 2563x = 1000; y = int("1000")4print(x is y) # False -> two different int objects5print(x == y) # TrueThis behaviour is an implementation detail, not a language rule. Python 3.8+ even prints a SyntaxWarning when you write is with a literal, such as x is 1000.
Why is None and not == None
None is a singleton — there is exactly one None object — so identity is the correct test. == None can be fooled: a class can define __eq__ to return anything, and in NumPy or pandas, array == None compares element by element and returns an array, not a single True/False.
For booleans, PEP 8 (Python's style guide) says to write if flag: — not if flag == True: and not if flag is True:.
A real-life example
A retrieval function returns a relevance score, or None when the search failed. A score of 0.0 is a real result: "nothing relevant".
1def next_step(score):2 if not score: # BUG: treats 0.0 like None3 return "retry search"4 return "use results"56def next_step_fixed(score):7 if score is None: # only a missing score triggers a retry8 return "retry search"9 return "use results" if score > 0.5 else "fallback answer"1011print(next_step(0.0), "|", next_step_fixed(0.0)) # retry search | fallback answer12print(next_step_fixed(None)) # retry searchThe buggy version retries every search that honestly found nothing, doubling API costs on hard queries. is None says exactly what you mean.
Follow-up questions to expect
- "What does
is notdo?" — The negated identity test. Writex is not None, which reads better thannot x is None. - "Can
a == bbeTruewhilea is bisFalse?" — Yes, whenever two separate objects hold equal values, like two lists with the same items. - "Can
x == xbeFalse?" — Yes:float("nan") == float("nan")isFalse, althoughx is xis alwaysTrue.