is operator
Updated March 16, 2026 · Keywords
keyword identity comparison objects
The is operator in Python compares object identity — it checks whether two references point to the exact same object in memory. This is different from equality (==), which checks whether two objects have the same value.
Syntax
result = object1 is object2
- Returns
Trueif both variables reference the same object - Returns
Falseif they reference different objects
Identity vs Equality
The Key Difference
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a is b) # False — different objects, same values
print(a is c) # True — same object
print(a == b) # True — same values
Why This Matters
# Using == (equality)
x = [1, 2, 3]
y = [1, 2, 3]
print(x == y) # True — contents are equal
# Using is (identity)
print(x is y) # False — they are different objects
Common Use Cases
Comparing with None
The most common use of is is checking for None:
value = None
# Correct way to check for None
if value is None:
print("No value provided")
# No value provided
value = 42
if value is not None:
print(f"Value is: {value}")
# Value is: 42
Why Not Use == for None?
# Both work, but is is preferred for None
value = None
print(value == None) # True
print(value is None) # True
# The difference matters with custom classes
class Sentinel:
def __eq__(self, other):
return True # Always returns True!
s = Sentinel()
print(s == None) # True — misleading!
print(s is None) # False — correct!
Comparing with Singletons
Python has a few singletons that should always be compared with is:
x = None
print(x is None) # True
x = True
print(x is True) # True
x = False
print(x is False) # True
Checking Mutable Default Arguments
A common gotcha:
def append_to(element, to=[]):
to.append(element)
return to
# The default list is created once and shared!
result1 = append_to(1)
result2 = append_to(2)
print(result1) # [1, 2] — shared default!
print(result2) # [1, 2]
print(result1 is result2) # True — same object!
The fix uses is:
def append_to(element, to=None):
if to is None:
to = [] # Create new list each call
to.append(element)
return to
result1 = append_to(1)
result2 = append_to(2)
print(result1) # [1]
print(result2) # [2]
print(result1 is result2) # False
Checking Object Type
Use isinstance() for type checking, not is:
x = "hello"
# Wrong
type(x) is str # Works but not recommended
# Correct
isinstance(x, str) # True
Custom Classes with eq
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
p1 = Point(1, 2)
p2 = Point(1, 2)
print(p1 == p2) # True — __eq__ says they are equal
print(p1 is p2) # False — different objects
When to Use is
| Use Case | Operator |
|---|---|
| Checking for None | is None / is not None |
| Comparing with True/False/NotImplemented | is True |
| Checking if mutable default was provided | is not None |
| Verifying object identity for caching | is |
| Comparing with Ellipsis (…) | is ... |
When NOT to Use is
| Use Case | Operator |
|---|---|
| Comparing numbers | == |
| Comparing strings | == |
| Comparing lists/tuples | == |
| Type checking | isinstance() |
Common Mistakes
Comparing Integers
# Don't do this — it is an implementation detail
a = 256
b = 256
print(a is b) # True (for small integers, CPython caches them)
a = 257
b = 257
print(a is b) # False — not cached!
# Always use == for numbers
print(a == b) # True
Comparing Strings
# Don't rely on string interning
a = "hello world"
b = "hello world"
print(a is b) # Might be True or False (implementation-dependent)
# Use == for comparison
print(a == b) # True
Boolean Confusion
# Don't compare with True/False directly
x = 1
# Works but unpythonic
if x == True:
# Pythonic way
if x: # Truthy check
# If you must check explicitly
if x is True: # Only matches actual True, not truthy values
Performance Note
is is slightly faster than == because it only compares memory addresses, not contents. However, the difference is negligible in most cases. Always prefer correctness over micro-optimization:
# Fast but wrong
if value is None: # Only works for None
# Correct
if value == None: # Works but misleading
# Pythonic
if value is None: # Correct and idiomatic
See Also
- in operator — membership testing
- not keyword — boolean negation
- isinstance() — type checking