PythonMastery

is checks identity, == checks value

== asks whether two values are equal; is asks whether they are the same object. Small-int caching hides the difference until it doesn't.

== asks "do these two values match?". is asks "are these the same object in memory?". Most of the time you want the first, and Python quietly caches small numbers in a way that makes the second look right in testing.

The surprise

python
a = 256
b = int("256")
print(a is b)

c = 1000
d = int("1000")
print(c == d, c is d)
output
True
True False

Same code, different answer. CPython keeps one shared object for every integer from -5 to 256, so 256 is 256 happens to hold. 1000 built at run time is a fresh object: equal in value, but not the same object.

The same thing happens with anything you copy:

python
orders_today = ["A-1", "A-2"]
orders_copy = list(orders_today)
print(orders_today == orders_copy, orders_today is orders_copy)
output
True False

The rule

Use == to compare values. Use is only when identity is the actual question: None, True, False, or a sentinel object you made yourself.

python
_MISSING = object()

def get_price(prices, item, default=_MISSING):
    if item in prices:
        return prices[item]
    if default is _MISSING:
        raise KeyError(item)
    return default

print(get_price({"tea": 2.5}, "tea"))
print(get_price({"tea": 2.5}, "coffee", None))
output
2.5
None

default is _MISSING can't be fooled: no value a caller passes, not even None, is that exact object.

Why it works

Every object has an identity (its id()), and is compares identities, which is fast and never calls any code. == calls the type's __eq__, which compares contents. Two lists, two strings or two big numbers can be equal without being one object.

When not to use it

Never write x is 1000 or name is "Ada". Python even warns about it (SyntaxWarning: "is" with 'int' literal) because whether it's True depends on caching details that change between versions. And x == None works, but x is None is the convention linters expect and is safe against classes with odd __eq__ methods.

Learn it properly: Operators & Expressions, Variables & Data Types