Variables & References
In Python a variable is a name bound to an object, not a box that holds a value. Grasping this makes mutability, aliasing and `is` vs `==` obvious.
Learning objectives
- › Explain that names are bound to objects, not the reverse
- › Distinguish `is` (identity) from `==` (equality)
- › Predict aliasing behaviour for mutable objects
- › Understand integer caching and interning surprises
Prerequisites
Simple explanation
What it is. A variable is a label attached to an object living in memory. Assignment `x = obj` makes the name `x` point at `obj`; it never copies the object.
Why it exists. Python's data model is uniform: everything is an object with an identity, a type and a value. Names are just references into that object graph, which is why the same object can have several names (aliases).
The problem it solves. This model explains aliasing, mutation-through-a-second-name, why default mutable arguments are dangerous, and the difference between identity and equality.
How it works. `id(x)` returns the object's identity (its address in CPython). `is` compares identities; `==` calls `__eq__` to compare values. Rebinding a name never affects other names bound to the same object — but mutating the shared object is visible through all of them.
Analogy: Objects are houses; variables are sticky notes with the address written on them. Several notes can point at one house. Repainting the house (mutation) is seen by everyone; moving a note to a new address (rebinding) affects only that note.
Common misconceptions
- "x = y copies the value." — It copies the reference; both names point at one object.
- "== and is are interchangeable." — `is` is identity; use `==` for value comparison (except for None, where `is None` is correct).
- "Small integers behaving oddly with is is a bug." — CPython caches small ints (-5..256), an implementation detail you shouldn't rely on.
Common alternatives
- copy.copy / copy.deepcopy when you truly need a separate object
Interactive visualization
Variable references visualizer
An animated, step-through variable references visualization is planned for this topic. The playable versions (closure, decorator, GIL and event-loop) are live now.
Code examples
Behind the scenes
- ▸Every object has an identity (id), a type, and a value; names live in namespaces mapping strings to objects.
- ▸Assignment binds a name to an object and increments the object's reference count.
- ▸CPython pre-allocates the integers -5..256 and interns many short strings, so `is` can surprisingly return True for them.
Interview insights
Key definitions
- · Identity: an object's unique id for its lifetime (id()).
- · Equality: whether two objects compare equal via __eq__ (==).
What's the difference between `is` and `==`?
Concise answer: `is` compares identity (same object in memory); `==` compares value via __eq__. Use `is` only for singletons like None.
Detailed answer: Two distinct lists with equal contents are `==` but not `is`. `is` is a pointer comparison of object identity. Beginners hit false positives with cached small ints and interned strings, which is why value comparisons must use ==.
Common mistake: Using `is` to compare strings or numbers.
Follow-ups:
- · Why is `x is 256` sometimes True?
Knowledge check
a = [1,2]; b = a; b.append(3); print(a) — output?
Which check is idiomatic for None?
Score: 0/2