Integer Interning — When is Accidentally Works Then Fails
Think of 'is' as checking if two remote controls are the exact same physical remote. '==' checks if two remote controls do the same thing (i.e., control the same TV channel). For small integers, Python might use the same physical remote (interning), but for others, it will give you two different physical remotes that happen to do the same thing.
The Setup
You are writing a rate-limiting middleware that validates API response status codes. Your test cases use standard codes like 200 and 400 and pass perfectly. However, once you deploy to production and handle a custom 503 response or large transactional ID bounds, the system starts failing basic equality checks.
What Does This Print?
def process_status(status_code):
# Checking identity instead of value
if status_code is 200:
return "OK"
elif status_code is 503:
return "Service Unavailable"
return "Unknown"
print(process_status(200))
print(process_status(int("200")))
print(process_status(503))
print(process_status(int("503")))
The Output
The comparison int("503") is 503 returns False, leading the function to return 'Unknown'. This occurs because is checks for object identity (memory address), whereas == checks for structural equality (value).
Why Python Does This
CPython optimizes memory allocation by caching and reusing singletons for small integers in the range [-5, 256]. Any execution that yields an integer in this range returns a reference to the pre-allocated global object. For integers outside this range (like 503), Python creates a brand-new integer object in memory every time. Thus, two distinct objects representing 503 have different memory addresses, making is comparisons fail.
The Fix
def process_status(status_code):
# Always use structural equality (==) for value comparisons
if status_code == 200:
return "OK"
elif status_code == 503:
return "Service Unavailable"
return "Unknown"
The '==' operator compares the values of objects, which is the desired behavior when checking if two numbers are numerically equivalent. It does not care about memory addresses or object identity, thus providing a reliable and consistent comparison.
How This Fails in Real Systems
An inventory tracking system checked item quantities using quantity is 0 to trigger restock notifications. It worked perfectly in staging (mostly small batches). In production, an ordering error spiked quantities, and when they depleted back to a non-cached integer threshold of 300, checks worked, but when querying isolated partition counts of 257, comparison failed, causing stock outs to go unnoticed.