Migrating from C++, Does Python do call by reference or call by?value?
Neil Pradhan
Full Stack Data & AI Engineer | Master's degree from KTH with specialization in Machine Learning
If you are migrating to python from C++, you will often come across this question about how are variables passed inside a python function. Is it pass-by-reference or pass-by-value? The answer to this question is pass by object reference, which is passed by value.
Confusing isn’t it?!!! Let me make it clear to you
Let me get to the point by using a simple example.
Let’s say that you have a list a = [1,2,3] you need to change the list to a =[43,34,55] at the same address, inside a function, without using return, how can you solve it?
Experiment 1:
a =[1,2,3]
print("original a:",a)
def change_list(l:list):
l = [43,34,55]
return l
change_list(a)
print("changed a:",a)
Output 1:
original a: [1, 2, 3]
changed a: [1, 2, 3]
Nothing has changed, everything remains the same throughout.
In python, variables are passed by reference but the reference is passed by value. This means that the reference you have inside change_list() is actually a copy of the reference you passed. This again implies that if you reassign the variable inside the function. It is a local variable existing only inside the function; re-assigning it won’t change anything in outside scopes.
Let us look at this experiment
Now, we will use a mutable operation such as [:]
a =[1,2,3]
def change_list(l:list):
l[:] = [43,34,55]
print("id of l:",id(l))
return l
print(a)
print("id of a:",id(a))
change_list(a)
print("id of a:",id(a))
print(a)
Output?:
[1, 2, 3]
id of a: 140600686866048
id of l: 140600686866048
id of a: 140600686866048
[43, 34, 55]
Hurry we have successfully changed our list members to new members, so now we have asserted that given a list l if we use l[:] = [43,34,55] will change the list that we pass through our function in the same reference as we expect.
Let’s talk about using the slicing operator “:” on the left side of the assignment operator, in this case, we create a shallow copy of the list that creates a different reference and therefore a different object. But be extremely careful when using this operator for 2 or higher dimensions of list as it will create two new references with shared lists. Examples are given in the conclusion.
Conclusion
Example
One Dimensional List
a =[1,2,3]
print("original a: ",a)
b = a[:] # creates two address it is a shallow copy
a[0] = 25
b[1] = 55
print("changed a:",a)
print("changed b:",b)
print(a is b)
OUTPUT:
original a: [1, 2, 3]
changed a: [25, 2, 3]
changed b: [1, 55, 3]
False
Shallow copy worked
a and b are changed and reflected changes respectively and separately.
But in the case of 2d lists, see the example below
Example when using “:”
a =[[1],[2],[3]]
print("original a:",a)
b = a[:]
a[0][0] = 25
b[1][0] = 55
print("changed a: ",a)
print("changed b: ",b)
print(a is b)
print(a[0] is b[0])
OUTPUT:
original a: [[1], [2], [3]]
changed a: [[25], [55], [3]]
changed b: [[25], [55], [3]]
False
True
a and b are changed but as lists are copied from a to b, the list copied are shared, and therefore we see False because a is not b but True when the list inside a that is a[0] is the same as the list inside b which is b[0]
Example when not using “:”
a =[[1],[2],[3]]
print("original a:",a)
b = [[j for j in i] for i in a]
a[0][0] = 25
b[1][0] = 55
print("changed a: ",a)
print("changed b: ",b)
print(a is b)
print(a[0] is b[0])
OUTPUT:
original a: [[1], [2], [3]]
changed a: [[25], [55], [3]]
changed b: [[25], [55], [3]]
True
True
As we see everything is true, a and b share the same resource including their lists inside completely.
Here the question is how then can we create two different entities in the case of 2d and 3d lists the answer to this problem is as follows:
a =[[1],[2],[3]]
print("original a:",a)
b = [[j for j in i] for i in a]
a[0][0] = 25
b[1][0] = 55
print("changed a: ",a)
print("changed b: ",b)
print(a is b)
print(a[0] is b[0])
OUTPUT:
original a: [[1], [2], [3]]
changed a: [[25], [2], [3]]
changed b: [[1], [55], [3]]
False
False
In this example we see everything is false, now we have successfully created two different entities a and b, also known as deep copy.
References: