Function Parameter Passing Mechanism in Python (Pass by Value vs Pass by Reference)
In Python, the function parameter passing mechanism is a concept that is often confusing but very important. Many people ask, "Is Python pass by value or pass by reference?" - In reality, Python uses "pass by object reference."
1. Understanding Basic Concepts
First, we need to clarify several basic concepts:
- Pass by Value: The function receives a copy of the argument; modifications to the parameter do not affect the original data.
- Pass by Reference: The function receives the address (reference) of the argument; modifications to the parameter affect the original data.
- Python's Object Model: In Python, everything is an object. Variables are actually references to objects (similar to pointers).
2. Python's Passing Mechanism: Pass by Object Reference
Python passes the reference (memory address) of an object, not the value of the object itself. This can be understood as "call by sharing" or "pass by object reference."
Let's understand this through specific examples:
def modify_number(x):
print(f"Before modification inside function: x = {x}, id = {id(x)}")
x = 10 # Reassignment
print(f"After modification inside function: x = {x}, id = {id(x)}")
num = 5
print(f"Before function call: num = {num}, id = {id(num)}")
modify_number(num)
print(f"After function call: num = {num}, id = {id(num)}")
The output will show:
- When reassigning inside the function, x points to a new object (integer 10).
- However, the external num still points to the original object (integer 5).
3. Differences Between Mutable and Immutable Objects
This is key to understanding parameter passing:
Immutable Objects: Numbers, strings, tuples, etc.
def modify_string(s):
print(f"Before modification inside function: s = {s}, id = {id(s)}")
s = s + " world" # Creates a new string
print(f"After modification inside function: s = {s}, id = {id(s)}")
text = "hello"
print(f"Before function call: text = {text}, id = {id(text)}")
modify_string(text)
print(f"After function call: text = {text}, id = {id(text)}")
Mutable Objects: Lists, dictionaries, sets, etc.
def modify_list(lst):
print(f"Before modification inside function: lst = {lst}, id = {id(lst)}")
lst.append(4) # Modifies the original list
print(f"After modification inside function: lst = {lst}, id = {id(lst)}")
my_list = [1, 2, 3]
print(f"Before function call: my_list = {my_list}, id = {id(my_list)}")
modify_list(my_list)
print(f"After function call: my_list = {my_list}, id = {id(my_list)}")
4. Key Distinctions Analysis
- For Immutable Objects: "Modifications" to parameters inside a function actually create new objects and do not affect the original variable.
- For Mutable Objects: The function can directly modify the content of the object, and such modifications will affect the original variable.
5. Special Cases: Reassignment vs. In-Place Modification
def test_modify(lst):
# Case 1: In-place modification (affects external)
lst.append(100)
# Case 2: Reassignment (does not affect external)
lst = [7, 8, 9] # This only changes the local variable lst's reference
my_list = [1, 2, 3]
test_modify(my_list)
print(my_list) # Output: [1, 2, 3, 100]
6. Practical Application Suggestions
Understanding this mechanism is important for writing correct Python code:
- If you don't want a function to modify an external mutable object, you can pass a copy:
func(mylist.copy())orfunc(mylist[:]). - For complex objects like dictionaries, use
copy.deepcopy()for deep copying. - Clearly distinguish between "modifying object content" and "reassigning a variable."
This parameter passing mechanism allows Python to maintain simplicity while providing sufficient flexibility.