Call by Value vs Call by Reference in Python

I was working with a team of data analysts in New York. We were optimizing some Python functions that handled large datasets.

During the review, one of the junior developers asked me: “Does Python use call by value or call by reference?”

This is a common question. I’ve been coding in Python for more than 10 years, and I can tell you, it’s not as easy as in languages like C++ or Java.

In this tutorial, I’ll explain the concept in simple terms. I’ll also show you examples with full code so you can test it yourself.

What Does Python Use?

Python doesn’t strictly use call by value or call by reference.

Instead, Python uses something called call by object reference (also known as call by sharing).

This means:

  • When you pass an object to a function, Python passes the reference to that object, not the actual object itself.
  • But whether you can change the original object depends on whether it’s mutable (like lists, dictionaries) or immutable (like integers, strings, tuples).

Method 1 – Example with Immutable Objects (Behaves Like Call by Value)

Let’s start with a simple example using integers.

def update_number(x):
    print("Inside function before change:", x)
    x = x + 10
    print("Inside function after change:", x)

num = 50
print("Before function call:", num)

update_number(num)

print("After function call:", num)

Output:

Before function call: 50
Inside function before change: 50
Inside function after change: 60
After function call: 50

I executed the above example code and added the screenshot below.

python passing by reference

Here, the value of num outside the function didn’t change. This happens because integers are immutable in Python. So in this case, it feels like a call by value.

Method 2 – Example with Mutable Objects (Behaves Like Call by Reference)

Now let’s try with a list.

def update_list(mylist):
    print("Inside function before change:", mylist)
    mylist.append(100)
    print("Inside function after change:", mylist)

data = [10, 20, 30]
print("Before function call:", data)

update_list(data)

print("After function call:", data)

Output:

Before function call: [10, 20, 30]
Inside function before change: [10, 20, 30]
Inside function after change: [10, 20, 30, 100]
After function call: [10, 20, 30, 100]

I executed the above example code and added the screenshot below.

call by value and call by reference in python

Here, the list data was modified inside the function, and the changes reflected outside as well. This feels like a call by reference.

Method 3 – Reassign a Mutable Object

There’s a twist! If you reassign the object inside the function, it won’t affect the original.

def reset_list(mylist):
    print("Inside function before reset:", mylist)
    mylist = [0, 0, 0]  # Reassigning
    print("Inside function after reset:", mylist)

data = [5, 6, 7]
print("Before function call:", data)

reset_list(data)

print("After function call:", data)

Output:

Before function call: [5, 6, 7]
Inside function before reset: [5, 6, 7]
Inside function after reset: [0, 0, 0]
After function call: [5, 6, 7]

I executed the above example code and added the screenshot below.

python call by reference

Notice that the original list data didn’t change. That’s because reassigning created a new object inside the function.

Method 4 – Example with Dictionaries

Dictionaries are also mutable, so they behave like lists.

def update_dict(my_dict):
    print("Inside function before change:", my_dict)
    my_dict["status"] = "active"
    print("Inside function after change:", my_dict)

user_info = {"name": "John", "city": "Chicago"}
print("Before function call:", user_info)

update_dict(user_info)

print("After function call:", user_info)

Output:

Before function call: {'name': 'John', 'city': 'Chicago'}
Inside function before change: {'name': 'John', 'city': 'Chicago'}
Inside function after change: {'name': 'John', 'city': 'Chicago', 'status': 'active'}
After function call: {'name': 'John', 'city': 'Chicago', 'status': 'active'}

The dictionary was updated inside the function, and the changes persisted outside.

Conclusion

  • Python uses call by object reference.
  • Immutable objects (int, str, tuple) behave like call by value.
  • Mutable objects (list, dict, set) behave like call by reference, but only if you modify them without reassigning.
  • Reassignment inside a function creates a new object and doesn’t affect the original.

When I first started coding in Python, I often got confused by this behavior. Over time, I realized it’s all about understanding mutability.

Once you know whether your object is mutable or immutable, it becomes much easier to predict how functions will behave.

You may read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.