9.10. Passing Mutable vs Immuatable Objects¶
Now that you have a deeper understanding of sequences, we need to revisit functions and parameters. In this section, we look at what happens when we pass mutable lists vs. unmutable tuples and strings to functions.
Take a look at the following code example. Can you predict what is printed out?
Use Show CodeLens to step through the code to see why the assignment to the formal parameter y
inside the double
function on (line 2) did not affect the global variable num
. An assignment to a formal parameter inside a function never
affects the argument in the caller.
9.10.1. Passing Lists¶
On the other hand, if you are passing a mutable object, such as a list, to a function, and the function alters the object’s state, that state change will be visible globally when the function returns. Take a look at the following example, where a list is passed in to a function.
Try stepping through this in Codelens to see what happens. The state of the list referenced by lst
is altered
by changeit
, and since lst
is an alias for mylst
, mylst
is affected by the actions taken by the function.
Look closely at this line:
lst[0] = "Manitoba"
That statement modifies the state of lst
by changing the value in slot 0. Although that line may appear to contradict the
statement above that “an assignment to a formal parameter inside a function never affects the argument in the caller,”
note that there is a difference between assigning to a slot of a list, and assigning to the list variable itself.
To see that difference, try changing that line to the following:
lst = ["Manitoba", "Bisons"]
Then, run again. This time, mylist
is not altered. To understand why, use CodeLens to step carefully through the code
and observe how the assignment to lst
causes it to refer to a separate list.
Take a moment to experiment some more with the changeit
function. Change the body of the function to the following:
lst.append(“Manitoba Bisons”)
Step through using CodeLens. You should see that mylst
is affected by this change, since the state of the list is altered.
Then, try again with this as the body:
lst = lst + ["Manitoba Bisons"]
Step through using CodeLens. Here, we create a new list using the concatenation operator, and mylst
is not affected by the change.
Understanding the techniques that functions can and cannot use to alter the state of mutable parameters is important. You may want to take some time to study the information on this page more thoroughly and play with the examples until you feel confident about your grasp of the material.
9.10.2. Passing Tuples¶
Tuples are just like lists, except they are not mutable. If you pass a tuple into a function and that function tries to modify the contents of it, an error will be thrown. Consider this example:
If you want this to work, you need to convert the tuple into a list, and then store a returned list:
9.10.3. Ethics & Data Protection¶
We most often use lists for storing data, because we often want the flexibility of being able to edit and change information. However, sometimes there is important data (private personal data, health data, salaries, etc.) that needs to be protected from tampering. As a programmer, if you need to share data but you want to ensure the data isn’t tampered with, you can send the data as a tuple. This allows a function to make use of the data, but not change it. Consider this example, which makes use of the accumulator pattern, reading from a tuple, but not modifying it:
The avg_salaries function could take a list or a tuple. By passing in a tuple, the programmer ensures the data is not modified. In this case, where the function is in the same file, it’s obvious that the list isn’t modified inside the function. But often you import modules and use functions that other people have written. As a programmer, you need to ensure that any private data you are responsible for isn’t modified inappropriately, and you can do this by using safe structures like tuples.
Check Your Understanding
[‘a’, ‘b’]
-
Correct!
mylist
is not changed by the assignment inmyfun
. [1, 2, 3]
-
Incorrect.
mylist
is not changed by the assignment inmyfun
.
What is the output of the following code fragment?
def myfun(lst):
lst = [1, 2, 3]
mylist = ['a', 'b']
myfun(mylist)
print(mylist)
[‘a’, ‘b’]
-
Incorrect.
myfun
alters the state of the list object by removing the value at slot 0. [‘b’]
-
Correct!
myfun
alters the state of the list object by removing the value at slot 0.
What is the output of the following code fragment?
def myfun(lst):
del lst[0]
mylist = ['a', 'b']
myfun(mylist)
print(mylist)