Pass by value vs Pass by reference. Why it’s important for Python developers?

Obi kastanya
4 min readFeb 4, 2024

--

Pass by value vs Pass by reference (Image generated by AI)

Passing an argument into a function in Python is tricky. Sometimes you get pass-by values, sometimes you get pass references. This kind of behavior would cost us errors or bugs if we weren’t aware of it.

In this article, I will tell you why it could crash our application, how exactly pass-by-value and pass-by-reference work in Python, and how to use them properly to avoid an error.

What is the difference between pass-by references and pass-by values?

In pass-by value, a copy from the original value is sent to the function as an argument. Any modification to the copy value will not affect the original value.

In pass-by-reference, the original value is sent to the function as an argument (reference). Modifications will affect the original value.

Why it’s important?

Let me explain it using a sample.
I have a Python script to count numbers. It will collect all the even numbers, sum the even numbers, and sum all numbers.

Now take a look at the result:

As you can see, the even number is counted correctly.

But when it tried to count the total numbers, all the numbers disappeared, so it counted as zero.

This happens because the pop action in the get_even_numbers function has removed all the actual numbers.

...
while numbers:
number = numbers.pop()
...

This is an example of how pass-by-reference could cause an error in our app.

In real-life applications, there are more codes. In this kind of situation, we should debug our application layer by layer to figure out when the value is changing and which code did it. Of course, it wastes so much time.

Understanding how pass-by-value and pass-by-reference work in Python is important to avoid facing this problem.

How do pass-by value and pass-by-reference work in Python?

These are the key points of passing arguments in Python:

  1. Immutable objects like string, boolean, number, and tuple are passed by value.
  2. Mutable objects like dictionary, list, set, and object are passed by reference.

Very simple. Let’s jump to the example.

I have a function to modify any value into None. Now let’s send our immutable object (string, boolean, number, and tuple) into the function.

Here are the results:

As you can see, the original value is not changing because it’s passed by value.

Next, let’s see how it works for the mutable objects (dictionary, list, set, and object). For that, I have to modify the set_to_none function to process values based on the data types.

Here are the results:

See, the original value is affected because it’s passed by reference.

How to avoid pass-by-reference.

Now you know that mutable objects are always passed as references. Often, we need to force them into pass-by-value. We could be doing it using copy and deepcopy functions.

These functions are built-in functions by Python.

Copy is used for simple data structures.

Deepcopy is used for nested data structures.

Take a look at this example
Use copy.

These are the results:

Perfect, all the values are passed by value. Any modification will not affect the original values because we use the copy function.

But what if there is a nested value?

Now take a look at this example. I add the address as a new attribute to the person object. The address is another object that has its attributes.

This is the result:

See, the address is still modified even though we already use the copy function.

This is because copy functions only copy the shallow attributes.

To handle nested attributes, we should use deepcopy. Deepcopy will copy all the attributes using recursive methods.

Modify this line to use deepcopy.

...
set_to_none(copy.deepcopy(person))
...

Here is the result.

Now, there is no original value changed, it’s all passed by value.

Perfect.

Thanks for reading my article.

--

--

Obi kastanya
Obi kastanya

Written by Obi kastanya

Python Developer | Backend Developer | Medium Writer

No responses yet