There are articles that call the strategy of python pass-by-value and others call pass-by-reference. The fact is python is always pass-by-reference. Then, where does this confusion come from? Why sometimes python acts like pass-by-value.
STATEMENT: if one pass the reference of an object, then the callee will share the same object as the caller. [This is TRUE] Any changes made to that object [troublemaker] in the callee _should_ reflect to its origin in the caller. We will show this statement might a little tricky. In the end, this article want to stand back on the assertion “Python is passing parameter by reference”.
Here we start from a example:
In that case, should the output of the program above be 7? The result however is 6. That is just like pass-by-value: instead of passing the reference, the value of x, i.e. 6, is passed to the function! That is why any changes made did not reflect to its origin. So, is that true? No! That is just an illusion. Python is always pass-by-reference. There two reasons explains this conflict. The statement we lay out at the beginning turns out not acculate, in the case of Python.
Mutable vs. Immutable
In python, there are two types of objects: mutable v.s. immutable, which basically tells wether the content of an object is subject to change or not. Immutable types include integer, strings, tuples etc, while mutable objects are list, set, dict. Since immutable objects should not be changed, any attempt to change them will implicitly instruct the program to create a new object (but a same name). We can use the identity function to justify our claim.
First, we create a immutable object, integer
This is the identiy of variable x, which is unique. Now, we try to change the value and look up its identiy again
That is! This object x (stores 7) is not the one (stores 6) we used to know!!
Now return to the function call. We can print their identies to test our theory:
>> def ref_demo(x):
… x = 7
>> x = 6
The first identiy is indeed same as the variable in caller, i.e. pass-by-reference. However, once we try to change the value, the identiy changed.
Thus, python follows pass-by-reference. It is different from C++ or other languages because it introduces mutable or immutable variables which makes the difference.
Assignment vs. Modification
There is another case also falsify our statement. See the example below.
>>> def ref_demo(l1):
… l1= l1 + [‘b’]
>>> ls = [‘a’]
We claimed that python is alsway passing by reference. The pass-by-value illusion is caused by immutable objects. But in this example, the conflict seems still legitimate for the case of mutable object. If pass-by-reference, why did we fail to change the content of the list?
Hers is the explain. We say that an object is mutable means it is possible to modify its content, which is not the same as an assignment. We know int variable x = 6 is immutable, but we can still perform an assignment x = 7 which creates a new variable. Here, l1 = l1 + [‘b’] consists of two steps: (1) addition operation of two lists (2) an assignment. And the second step creates a new object, forming a new list, whereas the changes was not able to reflect to its original list. We can use the same technique as above to justify this claim, i.e. the identify function.
So how to performa a modification then such that we can make changes to the original object because that is the purpose of pass-by-reference?
AFAIK, here are two ways:
(1) l1 += [‘b’]
(2) l1.append(‘b’) or l1.extend([‘b’]
The first one seems a little bit confused as usually we think it is a equivalent operation as l1 = l1 + [‘b’]. However, it’s not.
Using the rule of thumb, we can summarize both cases to the devil ‘assignment’. A reference is an alias of an variable/object, the attempt to change a reference, ie. assignment, will cause a creation of a new variable.
To conclude, in some cases, it is easy to get confused between pass-by-value and pass-by-reference because of exta rules imposed by ptyhon, but deep in the core, python follows pass-by-reference withou no doubt.