backend / python core / 19_args_passing_ref_value.md

Argument Passing in Python: By Reference or By Value?

3 interview angles 2 min read source

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.copy duplicates the container but shares the nested objects; copy.deepcopy recurses. Deep copy is expensive and breaks on unpicklable members, so prefer restructuring over reaching for it.