🧠 Python DeepCuts — 💡 Name Binding vs Assignment
Posted on: November 5, 2025
Description:
In Python, variables don’t “hold” values like boxes — they’re names bound to objects in memory.
Understanding this distinction helps you reason about how Python handles references, mutability, and side effects.
🧩 Variables Are Just Names
When you assign a value to a variable, Python binds that name to an existing object — it doesn’t copy the data.
a = [1, 2, 3]
b = a
print("a is b:", a is b) # True — both names refer to the same list
Now both a and b point to the same list in memory.
🔁 Rebinding vs Mutation
- Rebinding: assign a name to a new object
- Mutation: modify the contents of an existing object
a = [1, 2, 3]
b = a
a.append(4) # mutate — same object
print(a, b) # both change
a = [10, 20, 30] # rebind — a now points to a new list
print(a, b) # only a changes
This is why “pass-by-assignment” is a better way to describe how Python handles arguments.
🧩 Immutable Objects Behave Differently
Integers, floats, strings, and tuples are immutable — any “change” creates a new object.
x = 10
y = x
x += 5 # creates a new int object
print(x, y) # x: 15, y: 10
print(id(x), id(y)) # different IDs
Immutable objects can’t be modified in place, so every operation results in a new reference.
⚡ Mutability in Action: Lists vs Tuples
The += operator behaves differently for mutable and immutable types:
a = [1, 2]
b = a
a += [3, 4]
print(a is b) # True — list mutated in place
x = (1, 2)
y = x
x += (3, 4)
print(x is y) # False — new tuple created
Here’s the key:
- list.iadd() mutates
- tuple.add() creates a new object
🧭 Visualizing Name Binding
Think of names as arrows pointing to objects.
Multiple names can point to the same object — until one name is rebound.
data = {"key": [1, 2, 3]}
alias = data
alias["key"].append(4)
print(data, alias) # both changed
print(data is alias) # True
Both names reference the same dictionary, so mutation through one affects the other.
✅ Key Points
- ✅ Assignment binds names — it doesn’t copy data.
- ✅ Mutable objects change in place; immutable ones don’t.
- ✅ is checks identity; == checks value.
- ✅ Rebinding moves the label; mutation modifies the target.
- 🧠 Everything in Python is about names → objects → references.
Code Snippet:
import sys # to inspect object identity
a = [1, 2, 3] # create a list object
b = a # b is now another name pointing to the same list
print("a:", a)
print("b:", b)
print("a is b:", a is b) # True → same object
print("id(a):", id(a))
print("id(b):", id(b))
a = [1, 2, 3]
b = a # both refer to same list
print("Before mutation:", a, b)
a.append(4) # in-place mutation (list is mutable)
print("After mutation:", a, b) # both reflect the change
a = [10, 20, 30] # rebinding: a now points to a *new* list
print("After rebinding:", a, b) # b still refers to old list
x = 10
y = x # both names point to same int object
print("Before:", x, y)
print("id(x):", id(x))
print("id(y):", id(y))
x += 5 # new int created (since ints are immutable)
print("\nAfter x += 5:", x, y)
print("id(x):", id(x)) # different id → new object
print("id(y):", id(y)) # unchanged
# Mutable example
a = [1, 2]
b = a
a += [3, 4] # list.__iadd__ mutates in place
print("Lists → a is b:", a is b) # True
# Immutable example
x = (1, 2)
y = x
x += (3, 4) # tuple.__add__ creates a new object
print("Tuples → x is y:", x is y) # False
data = {"key": [1, 2, 3]}
alias = data
alias["key"].append(4)
print("Data:", data)
print("Alias:", alias)
print("Same object:", data is alias)
No comments yet. Be the first to comment!