I’ve seen many misconceptions about this even in Python lessons and tutorials that teach about the topic.
Let’s first take a look at what it all means.
In a pass-by-reference call, if the function makes an assignment to an argument, the original passed variable also changes.
In a pass-by-value call, if the function makes an assignment to an argument, only a local copy changes and the original stays the same.
Here is an example with a simple with a Python function:
def reset(z): z = 0
Now let’s this function:
x = 10 # <-- This is the original variable reset(x) print(x)
With pass-by-reference, this code would print 0.
With pass-by-value, this code would print 10.
What does Python do?
10
Python prints a 10! It’s pass-by-value.
The misconception comes with mutable objects such as lists. A mutable object is an object that can change its internal state.
In a list, when we assign a value at an index, we change the inside of the list:
lst = [1, 2, 3] lst[1] = 20 print(lst)
lst
is now,
[1, 20, 30]
It is possible to change the internal state of an object from inside a function, but not the object the variable is assigned to.
Here is a function that changes the first item of a list:
When we use it on a list, x = [1, 2, 3]
, the list changes. The variable x
still points to the same list, it’s just that one of it’s elements was changed.
def change_list(lst): lst[1] = 20
x = [1, 2, 3] change_list(x) print(x)
[1, 20, 30]
However, if an argument is reassigned to a different list, the original variable stays the same:
def reassign_list(lst): lst = [4, 5, 6]
x = [1, 2, 3] reassign_list(x) print(x) # x stays [1, 2, 3]
[1, 2, 3]
We assigned the argument a new list object inside the function, but Python prints the original object of [1,2,3]
. So it’s still pass-by-value. Python is only ever pass-by-value.