Hiprup

What is the difference between == and is in Python?

In Python, == and is answer two different questions. Mixing them up is one of the most common sources of subtle bugs.

  • == — equality of value. Calls the left operand’s __eq__ method; asks “do these two objects compare equal?”

  • is — identity. Compares the memory addresses (returned by id()); asks “are these two names pointing at the exact same object?”

Example:

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

a == b   # True  — same values
a is b   # False — different list objects
a is c   # True  — same object, two names

When to use which:

  • Use == for value comparisons: numbers, strings, collections, domain objects.

  • Use is only for checking against singletons or known sentinels — most commonly None: if x is None:. Also is True, is False, and sentinel patterns like a module-level _MISSING = object().

# Value equality (==) vs identity (is)
a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a == b)   # True  (same content)
print(a is b)   # False (different objects)
print(a is c)   # True  (same object)
print(id(a), id(b), id(c))  # a and c have same id

# Integer caching (implementation detail)
x = 256
y = 256
print(x is y)   # True  (cached)

x = 257
y = 257
print(x is y)   # False (not cached) — may vary!

# Correct None check
def greet(name=None):
    if name is None:     # CORRECT: use 'is' for None
        name = 'World'
    # if name == None:   # Works but not Pythonic
    print(f'Hello, {name}!')

a and b have the same content (== True) but are different objects in memory (is False). c = a makes c reference the same object as a (is True). Integer caching makes 256 is 256 True but 257 is 257 may be False.

None should always be checked with is None (identity), not == None (equality).

The None check (is None vs == None) is the most practical point. Always use is for None.

The integer caching gotcha (-5 to 256) is a classic interview question. Never use is for general value comparison.

What is the difference between == and is in Python? | Hiprup