Mutability, References and Copying: Interview Questions
50 min · Beginner
Need help? Ask a tutor on WhatsApp (opens in a new tab)"Why did my original list change?" is the most common Python surprise, and interviewers love it. The answer is always the same idea: names point to objects. This lesson turns that idea into short answers.
Recap: names, objects and mutability
A mutable object can change its contents after it is made, and every name pointing to it sees the change. Lists, dicts and sets are mutable; int, str and tuple are not.
A name is a label on an object. b = a adds a second label to the same object; it does not copy.
cart = ["pen"]alias = cartalias.append("book")print(cart)
price = 100other = priceother += 1print(price, other)If the object is mutable, a change through one name shows through the other.
Example 1 · Two names, one list
stock = ["pen", "book"]backup = stockbackup.append("bag")print(stock)print(stock is backup)safe = stock.copy()safe.append("ink")print(stock)print(safe)['pen', 'book', 'bag'] True ['pen', 'book', 'bag'] ['pen', 'book', 'bag', 'ink']
What this code does
backup = stockcopies nothing: both names reach one list, sostockshowsbag.stock.copy()builds a new list, so addinginktosafeleavesstockalone.
The list changed in place, so cart shows book. An int cannot change, so other += 1 made a new int and moved the label; price is untouched.
Recap: is vs ==
Identity is whether two names point to the very same object. a is b tests identity, while a == b tests whether the values are equal.
== asks if two objects hold the same value. is asks if they are one object. Use is for None, and == for everything else.
a = [1, 2]b = ac = a.copy()print(a is b, a is c, a == c)print(id(a) == id(b))Example 2 · is and == on equal values
x = [1, 2]y = [1, 2]print(x == y, x is y)value = Noneprint(value is None)name = "abc"print(name == "ab" + "c")True False True True
What this code does
xandywere built separately, so they are equal but not the same object.- Use
is Noneto test forNone, because there is only oneNoneobject. Compare strings and numbers with==, neveris.
b is another name for the same list, so is gives True. c is a separate list with equal contents: is is False, == is True.
Recap: shallow copy vs deepcopy
A shallow copy makes a new outer container but reuses the same inner objects. A deep copy also copies the inner objects, so nothing is shared.
list.copy(), lst[:] and copy.copy() are shallow. If the list holds other lists, both outer lists still share those inner lists.
import copy
orders = [["pen"], ["book"]]shallow = copy.copy(orders)deep = copy.deepcopy(orders)orders[0].append("ink")print(shallow[0])print(deep[0])Use copy.deepcopy when nested data must be fully separate.
Example 3 · The shallow copy trap
import copy
team = {"name": "A", "scores": [70, 80]}shallow = team.copy()deep = copy.deepcopy(team)team["scores"].append(90)team["name"] = "B"print(shallow)print(deep){'name': 'A', 'scores': [70, 80, 90]}
{'name': 'A', 'scores': [70, 80]}What this code does
shallowhas its ownnamekey, which staysA. But itsscoresis the same list asteam's, so it now shows90.deepcopycopied the inner list as well, sodeepkeeps the old scores.
shallow[0] is the same inner list as orders[0], so it shows ink. deep[0] is its own copy and does not.
Next step
Check your understanding
12 quick questions