Subsection9.11.1Mutable objects can change when passed to functions
When we pass mutable objects, like lists, to functions, the contents of those objects can be changed within the function. This is a side effect, if the object is not returned from the function. Consider the following example, which we have seen before:
When this code runs and we print out mylst, it looks different from whatβs in mylst on line 5. Again, in this example, the bison function is right there, so it isnβt hard to figure out why the list changed, but if there were 100 lines of code between the function definition and the function being called, it would be harder to understand and debug.
We can avoid confusing side effects when passing around mutable objects by passing in a copy of the object and then returning the modified copy and reassigning it to the variable. This makes it much more obvious that the function is altering the mutable object. Here is the code above rewritten to do this:
On line 7 in the code above, we use the built-in list() function, which takes a sequence as a parameter and returns a copy of that sequence as a list. Note also that we had to modify the function to return the list. Once these changes are made, the alterations to the list are no longer considered a side effect, as they are made transparent by returning a changed value.
Subsection9.11.2Side Effects in Interactive Programs
When we program interactively and use listener functions, we end up modifying global variables and objects and creating side effects. This is because the listener functions that you can register must only have the parameters relevant to the interaction event. Letβs revisit an earlier example:
In this interactive programming example, it isnβt possible to pass the turtle object (alex) to the listener functions key_r() or click() because these functionsβ parameters are confined to the parameters needed for responding to specific events. The key_r function is registered to execute when the user presses the r key and as a key listener function it takes no parameters. The click function is registered to execute when the user clicks the mouse and as a mouse-click listener function it must take two parameters so the operating system can pass in the information about where the user clicked the mouse (x and y). We can make this code have fewer side-effects by modifying it as shown below.
So, in the code above, we specify that we want to access and edit the global turtle variable (alex) in the listener functions key_r() and click(). Inside those functions, we call the other functions, but now we are passing them the turtle, they are modifying the turtle, and returning the turtle back to us. Now the only side-effects are the effects on the canvas (the square that is drawn, and the color and position of the turtle triangle representation). By returning the turtle object to the listener, we make it really clear that the turtle is changed by the random_square(), random_location() and random_colour() functions.
Check your understanding
Checkpoint9.11.1.
How many turtles are created in this script?
import turtle
import random
def write_msg(tom, msg, x, y):
tom.penup()
tom.goto(x,y)
tom.pendown()
tom.write(msg)
return tom
def here(x, y):
global alex
alex = write_msg(alex, "You clicked here!", x, y)
wn = turtle.Screen() # Set up the window and its attributes
alex = turtle.Turtle() # create alex
alex = write_msg(alex, "Hello!", 0, 0)
wn.onclick(here)
wn.listen()
none
A turtle named Alex is created on line 16
1
Yes, one turtle is created, and then is passed around and modified
2
A turtle is a mutable object, and it is passed around and modified in this program
It depends on how often the end user clicks
A turtle is a mutable object, and it is passed around and modified in this program
Checkpoint9.11.2.
What is a side effect of the write_msg function?
import turtle
import random
def write_msg(tom, msg, x, y):
tom.penup()
tom.goto(x,y)
tom.pendown()
tom.write(msg)
return tom
def here(x, y):
global alex
alex = write_msg(alex, "You clicked here!", x, y)
wn = turtle.Screen() # Set up the window and its attributes
alex = turtle.Turtle() # create alex
alex = write_msg(alex, "Hello!", 0, 0)
wn.onclick(here)
wn.listen()
There is no side effect, because the turtle is returned
Changes on the canvas are side effects.
The turtleβs internally stored coordinated are different
Because the turtle is a mutable object, and it is returned from the functions, changes to it are not considered side effects
A msg has been written on the canvas, and the turtle icon is in a different place
Yes changes to what the user sees on the canvas are side effects.
The turtle alex has been modified
Because the turtle is a mutable object, and it is returned from the functions, changes to it are not considered side effects