In this lesson, you’ll learn that Python doesn’t pass objects by value or reference. Python passes objects by assignment instead. In the examples, you’ll see how this differs when the object is mutable or immutable.
Object Passing in Python
00:13 This requires the object to be duplicated in memory, and the receiving function will only be able to access this new memory space. When you pass an object by reference, you pass a copy of just the memory address of the object.
00:29 In other words, a pointer. This can be much smaller than the actual object itself. Additionally, the receiving function can now use that memory address to modify the value there directly. At this point, you might be wondering, are function arguments in Python pass-by-value or pass-by-reference?
00:52 The answer is neither. Arguments are what the Python documentation calls pass-by-assignment, meaning that the parameters in the function being called point to the objects in memory that were passed into them as arguments.
It looks like pass-by-reference, but you have to remember that it doesn’t pass the memory address to the value of the object. It passes the address of the entire
PyObject, which itself contains the value.
In Python, we’re passing in a reference to a
PyObject in memory, which behaves differently depending on whether the passed-in object is immutable or mutable. If you pass an immutable type, like the string or
int, it mimics pass-by-value because you can’t actually modify
01:55 the object being passed in, anyway. A new object is always going to be created, which can then be returned from the function. This is why string functions often return the modified string because they can’t mutate the immutable string type directly.
However, even if you pass a mutable type, like a
list, if you reassign the parameter, instead of modifying its value, a separate object is created for it in memory, and that becomes inaccessible outside the scope of the function.
As usual, I’m here in Visual Studio Code in a new Python script. I’m going to start this by defining a function called
add_10, which will take a parameter and add 10 to it. Inside, I’ll use the
+= operator to
add 10. Outside this function, I will create a new integer name called
y which will point to a
PyObject with a value of 20. Then I will call
add_10, passing in
y, and finally, print out the value of
When we pass
y to the
add_10 function, what we’re really doing is telling it to create a new name
x, which is the parameter, and bind it to the same object in memory that
y points to. But then, because the type is immutable, incrementing
x by 10 really creates a new object in memory with the value 30, and
x is set to point to it. But
y does not point to it. That’s why printing the value of
y returns 20 still. I’m going to modify the function to instead append 10 to the end of a list that we pass in.
And it does! 10 now appears at the end of the list. The changes we made to
x within the function are reflected in
y, even though it’s outside the scope of the function. No new objects had to be created, so
y both point to this newly modified list.
We do have to be careful with how we use this, though. This means that if we use it in a way that does not call upon its mutability, this still won’t work. To demonstrate, I’m going to remove the call to the
append method, and instead, just reassign
x to a new
list object with random numbers.
We didn’t modify it using its mutability, we forced Python to change what
x was bound to. It follows that
y no longer point to the same object in memory, and so these changes are not seen outside the scope of this function.
Become a Member to join the conversation.