What's the difference between `is` and `==`?
Quick Answer
`==` calls `__eq__` and checks **value equality** (do these objects represent the same value?). `is` checks **identity** — whether two names point to the *same object in memory* (equivalent to `id(a) == id(b)`). Use `is` for singletons like `None`, `True`, `False`, and `is not` for sentinel checks; use `==` for comparing values.
Detailed Answer
== vs is
== invokes __eq__ and answers "are these values equal?" is answers
"are these literally the same object?" (identical id()).
a = [1, 2, 3]
b = [1, 2, 3]
c = a
a == b # True -- same contents
a is b # False -- two distinct list objects
a is c # True -- c is a name bound to the same object as a
Why a == b can be True while a is b is False
Two separate lists (or dicts, or custom objects with a custom __eq__)
can be equal in value without being the same object. The default
__eq__ inherited from object actually falls back to identity, but
built-in containers and most user classes override it to compare contents.
When to use is
Nonechecks: alwaysx is None, neverx == None.Noneis a singleton, andisavoids accidentally invoking a custom__eq__that might behave unexpectedly.- Singletons/sentinels:
x is True, or a private sentinel object (_MISSING = object()) used to distinguish "not provided" from "explicitlyNone". - Identity-sensitive logic: e.g., checking whether a cache returned the exact cached instance rather than an equal copy.
The small-integer/string trap
CPython caches small integers (-5 to 256) and some string literals, so
is can appear to work for equality by coincidence:
x = 256
y = 256
x is y # True (cached)
x = 257
y = 257
x is y # False on most builds — a new object, no caching guarantee
This is a CPython implementation detail, not part of the language spec —
relying on it for anything beyond None/True/False is a bug waiting to
happen.
Interview-ready summary: == compares values via __eq__; is
compares identity via id(). Always use is for None/singleton checks
and == for everything else — never rely on integer/string caching as a
substitute for ==.