Integer and String Interning
Overview
Python pre-allocates and caches small integers (`-5` to `256`) and certain strings (like identifiers or short strings without spaces) to save memory and improve performance. This is called 'interning'. When you assign one of these cached values to a variable, Python reuses the existing object in memory rather than creating a new one. status_code = 200 default_status = 200 print(status_code is default_status) # True Think of it like a library keeping multiple copies of popular books (the interned values) ready at the front desk, while rarely requested books (large numbers or long strings) have to be fetched from the back (created dynamically). This allows Python to use fast pointer comparison instead of slower character-by-character comparison for common values. timeout = 1000 max_retries = 1000 print(timeout is max_retries) # False (in most REPLs) Interning is a CPython implementation detail and is not guaranteed for large numbers or dynamically constructed strings. Because of how the compiler optimizes constants, the exact same script might behave differently in the REPL versus a file.
It optimizes memory usage and allows Python to use fast pointer comparison (identity check via `is`) instead of slower character-by-character comparison (equality check via `==`) for common values like dictionary keys or HTTP status codes.
Where used: Dictionary keys, HTTP status codes in FastAPI, Enum comparisons
Why learn this
- Explains why `is` sometimes behaves surprisingly compared to `==`.
- Helps understand memory optimization in Python.
- Prevents bugs where developers incorrectly rely on object identity for integers or strings.
Code walkthrough
status_ok = 200
response_status = 200
print(status_ok is response_status)
timeout_ms = 1000
max_timeout = 1000
print(timeout_ms is max_timeout)
Focus: The second `print` outputs `False` because integers above `256` are not guaranteed to be interned.
Aha moment
retry_count_1 = int('256')
retry_count_2 = int('256')
print(retry_count_1 is retry_count_2)
error_code_1 = int('257')
error_code_2 = int('257')
print(error_code_1 is error_code_2)
Prediction: What will the two print statements output?
Common guess: `True`, `True`
Python only caches integers up to `256`. For `257`, it creates two separate objects in memory, so `is` evaluates to `False` because they point to different memory locations.
Common mistakes
- Using `is` for value comparison: `a is b` checks if they are the exact same object in memory, which is only guaranteed for interned values like small integers, and can fail unpredictably across different environments. Always use `==` for value comparison.
Glossary
- pre-allocates
- Reserving memory space in advance for specific data before the program actually asks for it. Example: Python pre-allocates integer objects for `-5` to `256` at startup so they are ready instantly.
- identity check
- Comparing two variables to see if they point to the exact same object in the computer's memory. Example: `a is b` is an identity check — it is `True` only if `a` and `b` are the same object, not just equal in value.
Recall questions
- What is the specific range of integers that Python automatically interns?
- Why does Python intern certain strings and integers?
- Why shouldn't you rely on integer interning for numbers outside the `-5` to `256` range?
Understanding checks
What will this code print?
`True` `False`
Python caches small integers from `-5` to `256`. Variables assigned to `256` will point to the exact same memory address. For `257`, Python creates new separate objects.
A developer tries to check if a user's input equals a specific string by using `if user_input is 'admin':`. Why is this a bad idea?
The `is` operator checks for object identity (memory address), not value equality. While Python might intern the literal `'admin'`, it might not intern dynamically generated strings like user input.
Strings constructed at runtime are typically allocated at different memory addresses, so the identity check `is` will fail even if the content is perfectly identical. They should use `==` instead.
Practice tasks
Fix the Buggy Equality Check
This code attempts to check if two generated strings are equal using the `is` operator, but it will fail because strings from runtime operations are not always interned. Modify the code to correctly check if the values are identical, regardless of memory allocation.
Challenge
Checking identity of dictionary keys
You are building a caching system where you track if the user provided the exact same key object. Create a variable `key1` with the string `'user_id'` and another variable `key2` with the same string. Then create a dictionary `cache` and use `key1` to store the value `'data'`. Print `True` if `key2` is the exact same object as `key1` (using identity), and print the value from `cache` using `key2`.
Continue learning
Previous: Object identity: id() and memory references
Previous: Mutable vs immutable objects