14 May 2019

Understanding Pass by Reference vs. Pass by Value in Python

Understanding Pass by Reference vs. Pass by Value in Python

Programming languages often differ in how they handle the passing of arguments to functions. The terms commonly used to describe this behavior are “pass by reference” and “pass by value.” In this blog post, we’ll explore these concepts with code examples and clarify a common misconception: Python’s argument passing mechanism is actually “pass by assignment.”

Pass by Value

In languages that use pass by value, a copy of the argument’s value is passed to the function. Changes made to this copy do not affect the original variable. Let’s simulate what this would look like if Python used pass by value:

def modify_value(x):
    x = 10
    print("Inside function:", x)

x = 5
modify_value(x)
print("Outside function:", x)
## Output:
Inside function: 10
Outside function: 5

If Python were to use pass by value, the modify_value function would not be able to alter the original x. However, Python does not behave in this way—as we will see next.

Pass by Reference

In pass by reference, a reference to the actual argument is passed to the function. Any changes made in the function affect the argument outside the function. In languages that use pass by reference, we would see something like this:

def modify_reference(lst):
    lst.append(4)
    print("Inside function:", lst)

lst = [1, 2, 3]
modify_reference(lst)
print("Outside function:", lst)
## Output:
Inside function: [1, 2, 3, 4]
Outside function: [1, 2, 3, 4]

In pass by reference, changes inside the function affect the original list. Now, let’s see how Python actually handles these situations.

Pass by Assignment in Python

Python uses a mechanism known as “pass by assignment.” Variables in Python are names that point to objects, and when you pass an argument to a function, a new name (the parameter) is assigned to the original object. If that object is mutable (like a list), mutations will reflect in both the original and local names. Immutable types (like integers) seem to act as pass by value because reassigning within the function creates a new object.

Here’s an example with a mutable object (list):

def append_item(lst):
    lst.append(4)
    print("Inside function:", lst)

my_list = [1, 2, 3]
append_item(my_list)
print("Outside function:", my_list)
## Output:
Inside function: [1, 2, 3, 4]
Outside function: [1, 2, 3, 4]

And here’s an example with an immutable object (integer):

def increment(n):
    n += 1
    print("Inside function:", n)

number = 1
increment(number)
print("Outside function:", number)
## Output:
Inside function: 2
Outside function: 1

In both scenarios, Python “passes by assignment.” The list example reflects changes outside the function because lists are mutable. The integer example does not because integers are immutable, and n += 1 creates a new integer object inside the function.

Summary

Python’s pass by assignment is an elegant approach that simplifies how we reason about argument passing. Whether dealing with mutable or immutable objects, understanding this behavior allows Python programmers to write functions that behave predictably and avoid unintended side effects.

It’s crucial to recognize the type of object you’re dealing with and how changes to it inside a function can affect its state outside the function. With this knowledge, you can manipulate Python’s object model to achieve your desired outcomes in a clear and Pythonic way.

Happy coding!



Tags:
0 comments