Pass-By-Value vs Pass-By-Reference in Python
00:00 Because Python handles variables in a different way than languages like C++, Java, and Pascal do, we should expect the notions of pass-by-value and pass-by-reference to be a little bit different than from those other languages.
00:14 In C++, when you create an integer variable, the variable refers to a specific location in memory. When you assign a value to that variable, that value is written to that location in memory.
00:27 And then when you reassign it, the old value is just overwritten and the new value is put in its place.
00:36
Python does things differently. When I say x = 5
in Python, an object to represent the integer 5
is created, and x
is made to refer to that object.
00:48
There’s nothing specific about a particular memory location, wherever that may be. When I then reassign x
to 10
, a new object is created having nothing to do with the memory where the first object was made, and x
is simply made to refer to that new object.
01:07 And so Python doesn’t deal with memory locations in the direct way that a language like C++ might.
01:15
This is the same program that we had in C++. We define a function f()
to print out the value of its parameter, and here we’re going to do something a little bit different. To actually show the creation and manipulation of objects, we’re going to display the identifier, the unique number given to an object when it’s being used.
01:39
So, the output statement’s going to be a little bit different than it was in the C++ version, but the process is still going to be the same. In the function, we take a parameter, print out its value, change the value of that parameter, and print information about its new value and new object. In the main part of our program, we’re going to assign x
to be 5
, print out its value and its object identifier, call the function, and then print the value of x
again to see what, if any, effect the function had on the variable x
.
02:15
To run this, we would type python pass_by_assignment.py
.
02:26
And here’s what happened. x
was assigned to a value of 5
, and we have this identifier for the object that was created.
02:35
We then called the function and passed that object as the parameter. We see in the first output statement, fx
had a value of 5
, and its identifier—the same number referring to the same object that x
was.
02:53
Then we reassigned fx
to be the integer 10
,
02:58 and we can see a new object ID to indicate that a new object has been created.
03:04
But all of this is happening within the scope of the function f()
. Scope refers to when an identifier has meaning, and once this function quits execution, anything related to that function is gone.
03:20
So this change of fx
only happened within the scope of the function f()
. Once f()
is finished, all we have left is x
, and x
still has the value of 5
and is still referring to the same object that it was in the beginning.
03:39
The change of what the parameter was referring to didn’t have any effect on the object x
.
03:49 So, pass-by-assignment is the name we commonly use for this type of argument passing in Python. Parameter names are bound to the object when the function enters.
03:59 Whatever object is provided, that’s what the parameter refers to. Assignment also binds the name of a variable to an object. When a variable is bound to an immutable object, the object can’t be changed.
04:14 The variable can be bound to a new object, but we are not changing the contents of the object, we are replacing it with a new object. Other terms you might see for this are pass-by-object, pass-by-object-reference, or pass-by-sharing. A Python function can’t change the value of an argument by reassigning the corresponding parameter to something else. And pay attention to that word “reassigning,” because we will come back to that in the next lesson.
04:46 Let’s go ahead and take a look at this.
04:50
We’re going to define a function f()
, which takes a parameter x
. And we will completely ignore that parameter value, reassign x
to 'foo'
,
05:01
and that will be our function. And then—I’ve copied this for
loop header, I don’t want to type the whole thing, but let’s take a look at it—we are going to iterate over this tuple.
05:15
i
is, one at a time, going to be an integer, a dictionary, a set of integers, a string, and a list of strings.
05:25
We’re going to call f()
and pass the object i
to that function, and then we are going to print whatever i
is after f()
is executed.
05:39
So, the first time through, i
represents the integer 40
, f()
takes that object as x
, reassigns it to 'foo'
, and then the function ends. But again, that’s only in the scope of this function.
05:54
Once the function is done, i
has not been impacted at all. It is still referring to the same object, so we’ll see 40
. And similarly, all through this for
loop.
06:05
Even though x
refers to a new object after being given whatever object i
represents each time it’s called, it’s not changing the object that i
itself is referring to. So we can see the first time through i
is still 40
.
06:23
Even though that object was passed to x
and x
was reassigned to the object 'foo'
, x
no longer has anything to do with the object that i
refers to.
06:36
So, the first time through, we see that i
is the integer 40
, then it’s our dictionary, then it’s our set, then it’s our string, and then it’s our list.
06:48 You saw that you can’t change the value of an argument by reassigning its correspond parameter to something new. However, if the object is a mutable object, then the function can make changes to that object that it receives—not replacing it with a new object, but changing the object it received as an argument, and those changes will be reflected in the object that was passed to it when the function finishes its execution.
Become a Member to join the conversation.