Argument Passing in Python: By Reference or By Value?
What’s the Difference?
In programming, “pass by reference” and “pass by value” refer to how arguments are passed to functions:
- Pass by value: A copy of the actual value is passed. Changes inside the function don’t affect the original variable.
- Pass by reference: A reference (pointer) to the original variable is passed. Changes inside the function do affect the original variable.
Python’s Behavior
Python’s argument passing model is best described as:
“Pass-by-object-reference” (or “call by sharing”)
- Function arguments are references to objects, not copies.
- Whether you can modify the original object depends on its mutability.
Examples
Immutable objects (e.g. int, str, tuple)
def modify_number(x):
x += 10
print("Inside function:", x)
num = 5
modify_number(num)
print("Outside function:", num)
Output:
Inside function: 15
Outside function: 5
Explanation: int is immutable, so x += 10 creates a new object, and the original num is unchanged.
Mutable objects (e.g. list, dict, set)
def modify_list(my_list):
my_list.append(100)
items = [1, 2, 3]
modify_list(items)
print(items)
Output:
[1, 2, 3, 100]
Explanation: list is mutable, so changes inside the function affect the original list.
Summary Table
| Object Type | Example | Mutable? | Can it be changed in function? |
|---|---|---|---|
| int | 5 |
no | No |
| str | 'hello' |
no | No |
| list | [1, 2, 3] |
yes | Yes |
| dict | {"a": 1} |
yes | Yes |
| tuple | (1, 2) |
no | No |
Conclusion:
- Python always passes references to objects, not actual objects or copies.
- If the object is mutable, it can be changed inside the function.
- If the object is immutable, it cannot be changed, and reassigning creates a new local object.
Let me know if you’d like visual diagrams or more practice examples!
Interview angle
- “By value or by reference?” - neither; pass-by-object-reference. The function gets a reference to the same object, so mutating a list argument is visible to the caller, while rebinding the parameter name is not.
- “How do you avoid mutating a caller’s argument?” - copy explicitly inside the function, or accept an immutable type. Silently mutating an argument is a common source of action-at-a-distance bugs.
- “Shallow or deep copy?” -
copy.copyduplicates the container but shares the nested objects;copy.deepcopyrecurses. Deep copy is expensive and breaks on unpicklable members, so prefer restructuring over reaching for it.