def double_items(lst):
lst = [x * 2 for x in lst]
return lst
original = [1, 2, 3]
result = double_items(original)
print(original)
print(result)
What does original print?
If you said [1, 2, 3], you are right but possibly for the wrong reason.
If you said [2, 4, 6], you have the most common Python misconception about how function arguments work.
Python Is Neither Pass-by-Value Nor Pass-by-Reference
Every explanation I have seen frames this as Python being "pass-by-reference" for lists and "pass-by-value" for integers. This framing is wrong and it is why people keep getting confused.
Python is pass-by-object-reference. Or more precisely, names are bound to objects. Function arguments receive a reference to the same object the caller has. But what you do with that reference inside the function determines whether the original object changes.
Two Cases That Look Similar But Behave Differently
Case 1: Reassignment:
def modify(lst):
lst = [x * 2 for x in lst] # creates a NEW list, rebinds local name
return lst
original = [1, 2, 3]
modify(original)
print(original) # [1, 2, 3] — unchanged
Inside modify, lst = [x * 2 ...] creates a brand new list and binds the local name lst to it. The original list is untouched. The local name lst now points to a different object than original.
Case 2: Mutation:
def modify(lst):
for i in range(len(lst)):
lst[i] = lst[i] * 2 # mutates the SAME list in place
original = [1, 2, 3]
modify(original)
print(original) # [2, 4, 6] — changed
Here lst[i] = ... modifies the list object that both lst and original point to. The original is changed because both names reference the same object.
The Mental Model That Makes This Clear
Think of it this way. A Python name is a label attached to an object. When you pass a list to a function, you are giving the function a copy of the label, not a copy of the object.
If the function attaches its label to a different object (reassignment), the original label still points to the original object.
If the function uses its label to modify the object itself (mutation), the original label still points to the same now-modified object.
Why This Matters in Interviews
Interviewers use this pattern to distinguish candidates who understand Python's object model from those who have only memorized surface-level behavior. The follow-up question is almost always "what would you change to make the function modify the original" or "how would you prevent the function from modifying the original."
Both answers require understanding the difference between reassignment and mutation.
For more problems testing this concept and others like it, try PyCodeIt, free.
Top comments (0)