Explain mutable versus immutable types. Why does the distinction matter the moment you pass something into a function?
Immutable objects such as int, str and tuple cannot be changed after creation; lists, dicts and sets can. Python passes references, so a function receiving a mutable object can modify the caller's data in place. Rebinding the parameter name affects nothing outside the function.
Two functions that look almost identical behave completely differently.
def add_topping(order, topping):
order.append(topping) # mutates caller's list
def replace_order(order, new_items):
order = new_items # rebinds local name only
pizza = ["cheese"]
add_topping(pizza, "olives")
print(pizza) # ['cheese', 'olives']
replace_order(pizza, ["paneer"])
print(pizza) # ['cheese', 'olives'] ← unchanged
The parameter name is a local label pointing at the same object the caller passed. append reaches through that label and changes the object itself, which the caller sees. Assignment moves the label to a different object and leaves the original alone.
An immutable object cannot be reached through in that way at all, which is why passing an int or a string is always safe. s.upper() returns a new string; it does not modify s.
The failure this causes in real code is quiet. A helper that normalises a config dictionary and mutates it in place looks fine in isolation, and then a caller that expected its own dictionary untouched starts seeing modified values three functions away. When a function modifies its argument, either name it so that is obvious, or copy the input at the top and return the new object.
One thing worth knowing for the follow-up: immutability is shallow. A tuple cannot be reassigned, but if it holds a list, that list is still mutable.
row = ("BLR", ["delayed"])
row[1].append("cancelled") # works
That also means such a tuple is not hashable and cannot be used as a dictionary key.
- If Python passes references, why doesn't reassigning the parameter inside the function change the caller's variable?
- Which built-in types are immutable, and is a tuple always safe to share?
- How would you write a function that clearly signals it modifies its argument?