AW Dev Rethought

⚖️ There are two ways of constructing a software design: one way is to make it so simple that there are obviously no deficiencies - C.A.R. Hoare

🧠 Python DeepCuts — 💡 Name Binding vs Assignment


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)

Link copied!

Comments

Add Your Comment

Comment Added!