datarekha
Python Easy Asked at AmazonAsked at GoogleAsked at Microsoft

What is the difference between `is` and `==` in Python, and when does `is` give a surprising result?

The short answer

`==` calls `__eq__` and tests value equality. `is` tests object identity — whether two names point to the exact same object in memory. The surprise comes from CPython's interning: small integers (-5 to 256) and many short strings are cached, so `is` returns True even for separately created objects, but this is an implementation detail you must never rely on.

How to think about it

What the interviewer is really probing

This question is a classic way to check whether you understand Python’s object model — not just the syntax. The correct answer requires knowing that every Python value lives in memory as an object, and variables are just names that point to objects. == compares what those objects represent; is checks whether two names point to the exact same object.

The fundamental distinction

Think of two separate houses with the same floor plan. == says “do these layouts match?” — yes. is says “is this literally the same building?” — no.

== calls the object’s __eq__ method, which can be overridden to define what “equal” means for your type. is compares memory addresses via id() — no method call, no override possible.

a = [1, 2, 3]
b = [1, 2, 3]
c = a

a == b   # True  — same values
a is b   # False — different objects in memory

a is c   # True  — c is just another name for the same list object
id(a) == id(c)  # True — same memory address

The runnable demo — including the interning surprise

The key insight — why interning exists

CPython caches integers from -5 to 256 because they appear so frequently (loop counters, list lengths, boolean-like flags). Caching them saves memory and construction time. The same optimisation applies to short identifier-like strings that appear at compile time. This is a runtime implementation detail, not part of the Python language spec — PyPy or Jython may behave differently, and even CPython can change between releases.

The practical takeaway: is is essentially “do id() values match?” and id() is a memory address that happens to be stable only for the lifetime of the object.

The only safe uses of is

# Singleton checks — the one correct use case
if result is None:
    ...

if flag is True:   # rare; prefer plain `if flag:` unless strict True is needed
    ...

if obj is NotImplemented:
    ...
Learn it properly Variables & Types

Keep practising

All Python questions

Explore further

Skip to content