Skip to content

Passing by Reference in Python: Explained

CodeMDD.io

Pass by Reference in Python: Background and Best Practices

by Marius Mogyorosi

Defining Pass by Reference

Before diving into the technical details of passing by reference in Python, let’s understand the concept:

  • Pass means providing an argument to a function.
  • By reference means passing a reference to an existing variable to the function instead of an independent copy of the variable.

In Python, all function arguments are passed by reference, but the behavior might differ from what you expect if you are familiar with other programming languages. In Python, function arguments behave as references to objects in memory.

Contrasting Pass by Reference and Pass by Value

To understand pass by reference, it’s essential to contrast it with pass by value:

  • Pass by value: When a function is called with a value as an argument, a new copy of that value is created and passed to the function. Modifying the value within the function would not affect the original value.
  • Pass by reference: When a function is called with a reference to a variable as an argument, any modifications made to the referenced variable within the function would affect the original variable.

Python takes a unique approach. While all function arguments are passed by reference, the behavior might seem like a combination of pass by value and pass by reference due to the object’s mutability.

Using Pass by Reference Constructs

Now, let’s explore how pass by reference can be used in practice:

Avoiding Duplicate Objects

One advantage of pass by reference is avoiding the creation of duplicate objects when passing them to functions. Since objects are passed by reference, any modifications made to the object within the function would directly affect the original object.

def modify_list(items):
items.append(4)
numbers = [1, 2, 3]
modify_list(numbers)
print(numbers) # Output: [1, 2, 3, 4]

In the example above, the modify_list function modifies the numbers list by appending the value 4. The change made within the function affects the original numbers list.

Returning Multiple Values

Pass by reference allows functions to return multiple values by modifying arguments. By passing mutable objects as arguments and modifying them within the function, multiple values can be assigned to those objects.

def calculate_sum_and_product(a, b):
return a+b, a*b
x, y = 2, 3
sum_result, product_result = calculate_sum_and_product(x, y)
print(sum_result) # Output: 5
print(product_result) # Output: 6

The calculate_sum_and_product function calculates the sum and the product of two numbers. Instead of returning separate variables, it returns the sum and product by modifying the arguments a and b.

Creating Conditional Multiple-Return Functions

Pass by reference also allows the creation of conditional multiple-return functions. By modifying the arguments within the function, different values can be assigned to those arguments based on specific conditions.

def find_min_and_max(numbers):
if len(numbers) == 0:
return None, None
min_value = max_value = numbers[0]
for num in numbers:
if num < min_value:
min_value = num
if num > max_value:
max_value = num
return min_value, max_value
my_numbers = [5, 2, 7, 1, 9]
min_result, max_result = find_min_and_max(my_numbers)
print(min_result) # Output: 1
print(max_result) # Output: 9

In the find_min_and_max function, the minimum and maximum values in a list of numbers are determined by modifying the min_value and max_value variables. The function returns these values as multiple results.

Passing Arguments in Python

To understand how pass by reference works in Python, let’s examine how assignment and function arguments behave.

Understanding Assignment in Python

In Python, variables are references to objects in memory. When assigning a variable to another, the reference to the original object is copied, not the object itself.

x = 10
y = x
x = 20
print(y) # Output: 10

In the example above, the variable x is assigned the value 10. When the variable y is assigned x, the reference to the object representing 10 is copied to y. Therefore, modifying x does not affect the value of y.

Exploring Function Arguments

When passing arguments to a function in Python, the references to the objects are passed. If the object is mutable, any modifications made to the object within the function would affect the original object.

def modify_string(s):
s += " World"
greeting = "Hello"
modify_string(greeting)
print(greeting) # Output: Hello

In the example above, the modify_string function attempts to modify the variable s by concatenating ” World” to it. However, since strings are immutable, a new string is created. The original greeting variable remains unchanged.

Replicating Pass by Reference With Python

Although Python passes all function arguments by reference, there are ways to replicate the pass by reference behavior more explicitly:

Best Practice: Return and Reassign

One approach is to return the modified object from the function and reassigned the variable to the returned object.

def modify_list_v2(items):
items += [4]
return items
numbers = [1, 2, 3]
numbers = modify_list_v2(numbers)
print(numbers) # Output: [1, 2, 3, 4]

In this modified version of the modify_list function, instead of modifying the list in place, it returns a new list with the modifications. The output is the same, but the modification is achieved by reassigning the variable numbers to the returned list.

Best Practice: Use Object Attributes

Another approach is to use object attributes to achieve pass by reference behavior.

class DataContainer:
def __init__(self, data):
self.data = data
def modify_data(container):
container.data = 100
my_container = DataContainer(10)
modify_data(my_container)
print(my_container.data) # Output: 100

In this example, DataContainer is a class with a data attribute. By modifying the attribute within the modify_data function, the change affects the original object.

Best Practice: Use Dictionaries and Lists

Using dictionaries and lists is a common way to achieve pass by reference behavior in Python. Mutable objects like dictionaries and lists can be modified in place, allowing changes to propagate to the original object.

def modify_dict(dictionary):
dictionary['key'] = 'new value'
my_dict = {'key': 'value'}
modify_dict(my_dict)
print(my_dict) # Output: {'key': 'new value'}

In the modify_dict function, the dictionary is modified by adding a new key-value pair. The modified dictionary is accessible outside the function.

Conclusion

Pass by reference is a unique aspect of Python’s function argument behavior. While all arguments are passed by reference, understanding how mutable objects behave and employing best practices can help achieve the desired results. By avoiding duplicate objects, returning multiple values, and using mutable object attributes, pass by reference-like behavior can be replicated in Python.