Source From HerePreface
When you call a function in Python and give it some arguments... Are they passed by value? No! By reference? No! They're passed by assignment.
Many traditional programming languages employ either one of two models when passing arguments to functions:
Having said that, it is important to know the model that Python uses, because that influences the way your code behaves. In this Pydon't, you will:
Is Python pass-by-value?
In the pass-by-value model, when you call a function with a set of arguments, the data is copied into the function. This means that you can modify the arguments however you please and that you won't be able to alter the state of the program outside the function.
This is not what Python does, Python does not use the pass-by-value model. Looking at the snippet of code that follows, it might look like Python uses pass-by-value:
But, in fact, Python is not copying the data into the function. To prove this, I'll show you a different function:
Is Python pass-by-reference?
In a true pass-by-reference model, the called function gets access to the variables of the callee! Sometimes, it can look like that's what Python does, but Python does not use the pass-by-reference model.
I'll do my best to explain why that's not what Python does:
Here's some Pascal code:
What's the output of this program? If you run this, you'll see that the output is:
which can be rather surprising, if the majority of your programming experience is in Python!
Python object model
To really understand the way Python behaves when calling functions, it's best if we first understand what Python objects are, and how to characterise them.
The three characteristics of objects
In Python, everything is an object, and each object is characterised by three things:
Here is an object and its three characteristics:
As we can see above, id is the built-in function you use to query the identity of an object, and type is the built-in function you use to query the type of an object.
The (im)mutability of an object depends on its type. In other words, (im)mutability is a characteristic of types, not of specific objects! But what exactly does it mean for an object to be mutable? Or for an object to be immutable?
Recall that an object is characterised by its identity, its type, and its contents. A type is mutable if you can change the contents of its objects without changing its identity and its type. Lists are a great example of a mutable data type. Why? Because lists are containers: you can put things inside lists and you can remove stuff from inside those same lists.
Below, you can see how the contents of the list obj change as we make method calls, but the identity of the list remains the same:
However, when dealing with immutable objects, it's a completely different story. If we check an English dictionary, this is what we get for the definition of “immutable”:
Immutable objects' contents never change. Take a string as an example:
Strings are a good example for this discussion because, sometimes, they can look mutable. But they are not!
A very good indicator that an object is immutable is when all its methods return something. This is unlike list's .append method, for example! If you use .append on a list, you get no return value. On the other hand, whatever method you use on a string, the result is returned to you:
Notice how obj wasn't updated automatically to "HELLO, WORLD!". Instead, the new string was created and returned to you.
Another great hint at the fact that strings are immutable is that you cannot assign to its indices:
This shows that, when a string is created, it remains the same. It can be used to build other strings, but the string itself always. stays. unchanged.
Variable names as labels
Another important thing to understand is that a variable name has very little to do with the object itself.
In fact, the name obj was just a label that I decided to attach to the object that has identity 2698212637504, has the list type, and contents 1, 2, 3. Just like I attached the label obj to that object, I can attach many more names to it:
Again, these names are just labels. Labels that I decided to stick to the same object. How can we know it's the same object? Well, all their “social security numbers” (the ids) match, so they must be the same object:
Therefore, we conclude that foo, bar, baz, and obj, are variable names that all refer to the same object.
The operator is
This is exactly what the operator is does: it checks if the two objects are the same.
For two objects to be the same, they must have the same identity:
It is not enough to have the same type and contents:
Think of it in terms of perfect twins. When two siblings are perfect twins, they look identical. However, they are different people!
Assignment as nicknaming
If we keep pushing this metaphor forward, assigning variables is just like giving a new nickname to someone.
My friends from middle school call me “Rojer”. My friends from college call me “Girão”. People I am not close to call me by my first name – “Rodrigo”. However, regardless of what they call me, I am still me, right?
If one day I decide to change my haircut, everyone will see the new haircut, regardless of what they call me!
In a similar fashion, if I modify the contents of an object, I can use whatever nickname I prefer to see that those changes happened. For example, we can change the middle element of the list we have been playing around with:
Because they all pointed at the same list object.
Python is pass-by-assignment
Having laid out all of this, we are now ready to understand how Python passes arguments to functions. When we call a function, each of the parameters of the function is assigned to the object they were passed in. In essence, each parameter now becomes a new nickname to the objects that were given in.
If we pass in immutable arguments, then we have no way of modifying the arguments themselves. After all, that's what immutable means: “doesn't change”.
That is why it can look like Python uses the pass-by-value model. Because the only way in which we can have the parameter hold something else is by assigning it to a completely different thing. When we do that, we are reusing the same nickname for a different object:
On the other hand, mutable arguments can be changed. We can modify their internal contents. A prime example of a mutable object is a list: its elements can change (and so can its length).
That is why it can look like Python uses a pass-by-reference model. However, when we change the contents of an object, we didn't change the identity of the object itself. Similarly, when you change your haircut or your clothes, your social security number does not change:
More topics (Making copies, Examples in code etc) can refer to original post here.