Fall 2011 CSCI 220 Week 8

The Function of Functions
Functions are an important tool for building sophisticated programs. Programs that we have written so far comprise a single function or no functions at all. We've typically called this function main.

We've used pre-written functions and methods including built-in Python functions (e.g., abs, eval), functions and methods from the Python standard libraries (e.g., math.sqrt), and methods from the graphics module (e.g., myPoint.getX).

What if we wanted to write a program that created a street full of houses instead of just one on our greeting card from last week. I'm going to shamelessly borrow the house from the overall winner of the competition. Here is the original code. from graphics import* from time import sleep import random

win = GraphWin("Season Greetings", 400, 400)

win.setCoords(0, 0, 200, 200)

sky = Rectangle(Point(0, 50), Point(200, 200)) sky.setFill(color_rgb(0, 10, 60)) sky.draw(win)
 * Sky

roof= Polygon(Point(80, 120),Point(110, 110),Point(50, 110)) roof.setFill(color_rgb(30, 20, 30)) roof.draw(win)
 * 1) Roof of House

house = Rectangle(Point(110, 110), Point(50, 50)) house.setFill(color_rgb(65, 75, 85)) house.draw(win) window = Rectangle(Point(100, 90), Point(80, 70)) window.setFill('lightblue') window.draw(win) window1 = Line(Point(90, 90), Point(90, 70)) window1.draw(win) window2 = Line(Point(100, 80), Point(80, 80)) window2.draw(win) door = Rectangle(Point(70, 70), Point(60, 50)) door.setFill('red') door.draw(win) doorknob = Circle(Point(62.25, 60), 1) doorknob.setFill('yellow') doorknob.draw(win)
 * 1) House

garage = Rectangle(Point(150, 80), Point(110, 50)) garage.setFill(color_rgb(65, 75, 85)) garage.draw(win) garageroof = Polygon(Point(130, 90), Point(150, 80), Point(110, 80)) garageroof.setFill(color_rgb(30, 20, 30)) garageroof.draw(win) groof1 = Line(Point(130, 90), Point(150, 80)) groof1.draw(win) groof2 = Line(Point(150, 80), Point(110, 80)) groof2.draw(win) groof3 = Line(Point(110, 80), Point(130, 90)) groof3.draw(win) gdoor = Rectangle(Point(140, 70), Point(120, 50)) gdoor.setFill(color_rgb(30, 20, 30)) gdoor.draw(win) gwindow = Rectangle(Point(125.5, 70.25), Point(137.5, 77.5)) gwindow.setFill('lightblue') gwindow.draw(win)
 * 1) Garage

ground = Rectangle(Point(0, 0), Point(200, 50)) ground.setFill('green') ground.draw(win)
 * 1) Ground

COLOR_TREE = color_rgb(120, 160, 56)

top = Polygon(Point(20,100), Point(25, 90), Point(15, 90)) top.setFill(COLOR_TREE) top.draw(win) middle = Polygon(Point(20, 90), Point(30, 80), Point(10, 80)) middle.setFill(COLOR_TREE) middle.draw(win) bottom = Polygon(Point(20, 80), Point(35, 60), Point(5, 60)) bottom.setFill(COLOR_TREE) bottom.draw(win)
 * 1) Tree

trunk = Rectangle(Point(17.5, 50), Point(22.5, 60)) trunk.setFill('brown') trunk.draw(win)

sun = Circle(Point(50, 170), 15) sun.setFill('lightyellow') sun.draw(win)
 * 1) Moon

instructions = Text(Point(110, 140), "Click anywhere 10 times to make it snow!") instructions.setFill('red') instructions.setSize(7) instructions.draw(win)

win.getMouse instructions.undraw

numClicks = 10 snowflake = Circle(Point(130, 170), 1.75) snowflake.setFill('white') snowflake.draw(win) for i in range(numClicks): p = win.getMouse c = snowflake.getCenter
 * 1) Snowflake
 * 1) newflakes = []

dx = p.getX - c.getX dy = p.getY - c.getY

newsnow = snowflake.clone newsnow.move(dx, dy) newsnow.draw(win)

instructions.setText("click again to see what happenes next!") instructions.draw(win) win.getMouse instructions.undraw
 * 1) Fading Stuff

ground.setFill('white')

light1 = Circle(Point(11, 65), 2) light1.setFill('red') light1.draw(win) light2 = Circle(Point(25, 65), 2) light2.setFill('yellow') light2.draw(win) light3 = Circle(Point(20, 70), 2) light3.setFill('green') light3.draw(win) light4 = Circle(Point(15, 84), 2) light4.setFill('yellow') light4.draw(win) light5 = Circle(Point(24, 82), 2) light5.setFill('green') light5.draw(win) light6 = Circle(Point(20, 93), 2) light6.setFill('red') light6.draw(win)
 * 1) Light

lights = [] lights.append(light1) lights.append(light2) lights.append(light3) lights.append(light4) lights.append(light5) lights.append(light6)


 * 1) Snowman

snowman = [] head = Circle(Point(175, 72), 2) snowman.append(head) middle = Circle(Point(175, 65), 4) snowman.append(middle) last = Circle(Point(175, 55), 6) snowman.append(last) for snow in snowman: snow.setFill('white') snow.draw(win)


 * W

ww = Circle(Point(65, 82), 8) ww.setFill('green') ww.draw(win) w = Circle(Point(65, 82), 4) w.setFill(color_rgb(65, 75, 85)) w.draw(win) lw = Circle(Point(65, 88), 1.5) lw.setFill('red') lw.draw(win) lw2 = Circle(Point(65, 77), 1.5) lw2.setFill('red') lw2.draw(win) lw3 = Circle(Point(60, 81), 1.5) lw3.setFill('red') lw3.draw(win) lw4 = Circle(Point(71, 82), 1.5) lw4.setFill('red') lw4.draw(win)

message= Text(Point(90,30), "Season Greetings!") message.setFill('red') message.draw(win)

newflakes = [] numClicks = 825 colors = ['yellow', 'green', 'red', 'blue', 'orange'] for i in range(numClicks): px = int(win.width * random.random) py = int(win.height * random.random) p = Point(px, py) newflake = Circle(p, 1.75) newflake.setFill('white') newflake.draw(win) newflakes.append(newflake)

for i in range(win.height): for flake in newflakes: flake.move(0, -random.random) for light in lights: coli = int(random.random * len(colors)) light.setFill(colors[coli])

sleep(0.025)

instructions.setText("click again to close!") mag = message.getAnchor iga = instructions.getAnchor instructions.move(mag.getX - iga.getX + 20, mag.getY - iga.getY - 6) instructions.draw(win) win.getMouse win.close

That is a lot of code, and it was a great card, but let's see how we can apply functions to make it even better. We can start by looking for patterns of repeated code. The code does not have to be identical. Before we do that, we need to set down a few basics.

Some basics

 * Functions can be thought of as a subprogram.
 * The basic idea is that we write a sequence of statements and give that sequence a name.
 * Those statements can then be executed by referring to the function name.
 * When our subprogram or function is executed we say that the definition is being called or invoked.

First steps
In the program above, the section that generates the light has a nice repetitive pattern. light1 = Circle(Point(11, 65), 2) light1.setFill('red') light1.draw(win) light2 = Circle(Point(25, 65), 2) light2.setFill('yellow') light2.draw(win) light3 = Circle(Point(20, 70), 2) light3.setFill('green') light3.draw(win) light4 = Circle(Point(15, 84), 2) light4.setFill('yellow') light4.draw(win) light5 = Circle(Point(24, 82), 2) light5.setFill('green') light5.draw(win) light6 = Circle(Point(20, 93), 2) light6.setFill('red') light6.draw(win)
 * 1) Light

The code is:
 * 1) Call the constructor of the Circle class
 * 2) Call the set fill functions and set the color
 * 3) Call the draw method on the window

We can create a function that corresponds to that sequence: def create_light: light = Circle(Point(11, 65), 2) light.setFill('red') light.draw(win)

But there are some problems with the function. What are they?

We want to replace the original code with something that looks like: create_light
 * 1) Light
 * 2) light1 = Circle(Point(11, 65), 2)
 * 3) light1.setFill('red')
 * 4) light1.draw(win)

create_light
 * 1) light2 = Circle(Point(25, 65), 2)
 * 2) light2.setFill('yellow')
 * 3) light2.draw(win)

create_light
 * 1) light3 = Circle(Point(20, 70), 2)
 * 2) light3.setFill('green')
 * 3) light3.draw(win)

create_light
 * 1) light4 = Circle(Point(15, 84), 2)
 * 2) light4.setFill('yellow')
 * 3) light4.draw(win)

create_light
 * 1) light5 = Circle(Point(24, 82), 2)
 * 2) light5.setFill('green')
 * 3) light5.draw(win)

create_light
 * 1) light6 = Circle(Point(20, 93), 2)
 * 2) light6.setFill('red')
 * 3) light6.draw(win)

Problems:
 * 1) Every light is drawn at the same location
 * 2) Every light is the same color
 * 3) win object is undefined. This is because win is outside of the scope of the function

These problems can be fixed by using arguments or parameters to the function. A parameter is a variable that is initialized when the function is called. Now we can make the changes to the create_light function: def create_light(window,x,y,color): light = Circle(Point(x, y), 2) light.setFill(color) light.draw(window)

Note that I've changed the name of the GraphWin variable from win to window. The scope of these parameters are the function themselves, so we can name them whatever we want. Now we can update our code:

create_light(win,11,65,'red')
 * 1) Light
 * 2) light1 = Circle(Point(11, 65), 2)
 * 3) light1.setFill('red')
 * 4) light1.draw(win)

create_light(win,25,65,'yellow')
 * 1) light2 = Circle(Point(25, 65), 2)
 * 2) light2.setFill('yellow')
 * 3) light2.draw(win)

create_light(win,20,70,'green')
 * 1) light3 = Circle(Point(20, 70), 2)
 * 2) light3.setFill('green')
 * 3) light3.draw(win)

create_light(win,15,84,'yellow')
 * 1) light4 = Circle(Point(15, 84), 2)
 * 2) light4.setFill('yellow')
 * 3) light4.draw(win)

create_light(win,24,82,'green')
 * 1) light5 = Circle(Point(24, 82), 2)
 * 2) light5.setFill('green')
 * 3) light5.draw(win)

create_light(win,20,93,'red')
 * 1) light6 = Circle(Point(20, 93), 2)
 * 2) light6.setFill('red')
 * 3) light6.draw(win)

We are almost finished, but if we look further into the program we see: lights = [] lights.append(light1) lights.append(light2) lights.append(light3) lights.append(light4) lights.append(light5) lights.append(light6)

This will present a problem because the scope of our light variable inside our function is only the function itself. But we fix this problem by returning the light object after the function is completed. This is done be adding a return statement at the very end of our function: def create_light(window,x,y,color): light = Circle(Point(x, y), 2) light.setFill(color) light.draw(window) return light

Now our code to create the lights looks like: light1 = create_light(win,11,65,'red') light2 = create_light(win,25,65,'yellow') light3 = create_light(win,20,70,'green') light4 = create_light(win,15,84,'yellow') light5 = create_light(win,24,82,'green') light6 = create_light(win,20,93,'red')
 * 1) Light

Not only does this reduce the number of lines and redundancy of the program, it also improves readability. Now we can put this all together with our original program:

from graphics import* from time import sleep import random

def create_light(window,x,y,color): light = Circle(Point(x, y), 2) light.setFill(color) light.draw(window) return light

win = GraphWin("Season Greetings", 400, 400)

win.setCoords(0, 0, 200, 200)

sky = Rectangle(Point(0, 50), Point(200, 200)) sky.setFill(color_rgb(0, 10, 60)) sky.draw(win)
 * Sky

roof= Polygon(Point(80, 120),Point(110, 110),Point(50, 110)) roof.setFill(color_rgb(30, 20, 30)) roof.draw(win)
 * 1) Roof of House

house = Rectangle(Point(110, 110), Point(50, 50)) house.setFill(color_rgb(65, 75, 85)) house.draw(win) window = Rectangle(Point(100, 90), Point(80, 70)) window.setFill('lightblue') window.draw(win) window1 = Line(Point(90, 90), Point(90, 70)) window1.draw(win) window2 = Line(Point(100, 80), Point(80, 80)) window2.draw(win) door = Rectangle(Point(70, 70), Point(60, 50)) door.setFill('red') door.draw(win) doorknob = Circle(Point(62.25, 60), 1) doorknob.setFill('yellow') doorknob.draw(win)
 * 1) House

garage = Rectangle(Point(150, 80), Point(110, 50)) garage.setFill(color_rgb(65, 75, 85)) garage.draw(win) garageroof = Polygon(Point(130, 90), Point(150, 80), Point(110, 80)) garageroof.setFill(color_rgb(30, 20, 30)) garageroof.draw(win) groof1 = Line(Point(130, 90), Point(150, 80)) groof1.draw(win) groof2 = Line(Point(150, 80), Point(110, 80)) groof2.draw(win) groof3 = Line(Point(110, 80), Point(130, 90)) groof3.draw(win) gdoor = Rectangle(Point(140, 70), Point(120, 50)) gdoor.setFill(color_rgb(30, 20, 30)) gdoor.draw(win) gwindow = Rectangle(Point(125.5, 70.25), Point(137.5, 77.5)) gwindow.setFill('lightblue') gwindow.draw(win)
 * 1) Garage

ground = Rectangle(Point(0, 0), Point(200, 50)) ground.setFill('green') ground.draw(win)
 * 1) Ground

COLOR_TREE = color_rgb(120, 160, 56)

top = Polygon(Point(20,100), Point(25, 90), Point(15, 90)) top.setFill(COLOR_TREE) top.draw(win) middle = Polygon(Point(20, 90), Point(30, 80), Point(10, 80)) middle.setFill(COLOR_TREE) middle.draw(win) bottom = Polygon(Point(20, 80), Point(35, 60), Point(5, 60)) bottom.setFill(COLOR_TREE) bottom.draw(win)
 * 1) Tree

trunk = Rectangle(Point(17.5, 50), Point(22.5, 60)) trunk.setFill('brown') trunk.draw(win)

sun = Circle(Point(50, 170), 15) sun.setFill('lightyellow') sun.draw(win)
 * 1) Moon

instructions = Text(Point(110, 140), "Click anywhere 10 times to make it snow!") instructions.setFill('red') instructions.setSize(7) instructions.draw(win)

win.getMouse instructions.undraw

numClicks = 10 snowflake = Circle(Point(130, 170), 1.75) snowflake.setFill('white') snowflake.draw(win) for i in range(numClicks): p = win.getMouse c = snowflake.getCenter
 * 1) Snowflake
 * 1) newflakes = []

dx = p.getX - c.getX dy = p.getY - c.getY

newsnow = snowflake.clone newsnow.move(dx, dy) newsnow.draw(win)

instructions.setText("click again to see what happenes next!") instructions.draw(win) win.getMouse instructions.undraw
 * 1) Fading Stuff

ground.setFill('white')

light1 = create_light(win,11,65,'red') light2 = create_light(win,25,65,'yellow') light3 = create_light(win,20,70,'green') light4 = create_light(win,15,84,'yellow') light5 = create_light(win,24,82,'green') light6 = create_light(win,20,93,'red')
 * 1) Light
 * 2) Light

lights = [] lights.append(light1) lights.append(light2) lights.append(light3) lights.append(light4) lights.append(light5) lights.append(light6)


 * 1) Snowman

snowman = [] head = Circle(Point(175, 72), 2) snowman.append(head) middle = Circle(Point(175, 65), 4) snowman.append(middle) last = Circle(Point(175, 55), 6) snowman.append(last) for snow in snowman: snow.setFill('white') snow.draw(win)


 * W

ww = Circle(Point(65, 82), 8) ww.setFill('green') ww.draw(win) w = Circle(Point(65, 82), 4) w.setFill(color_rgb(65, 75, 85)) w.draw(win) lw = Circle(Point(65, 88), 1.5) lw.setFill('red') lw.draw(win) lw2 = Circle(Point(65, 77), 1.5) lw2.setFill('red') lw2.draw(win) lw3 = Circle(Point(60, 81), 1.5) lw3.setFill('red') lw3.draw(win) lw4 = Circle(Point(71, 82), 1.5) lw4.setFill('red') lw4.draw(win)

message= Text(Point(90,30), "Season Greetings!") message.setFill('red') message.draw(win)

newflakes = [] numClicks = 825 colors = ['yellow', 'green', 'red', 'blue', 'orange'] for i in range(numClicks): px = int(win.width * random.random) py = int(win.height * random.random) p = Point(px, py) newflake = Circle(p, 1.75) newflake.setFill('white') newflake.draw(win) newflakes.append(newflake)

for i in range(win.height): for flake in newflakes: flake.move(0, -random.random) for light in lights: coli = int(random.random * len(colors)) light.setFill(colors[coli])

sleep(0.025)

instructions.setText("click again to close!") mag = message.getAnchor iga = instructions.getAnchor instructions.move(mag.getX - iga.getX + 20, mag.getY - iga.getY - 6) instructions.draw(win) win.getMouse win.close

Formal definition of a function
def ():

A function is called by def ()

When Python comes to a function call, it initiates a four-step process:
 * 1) The calling program suspends execution at the point of the call.
 * 2) The format parameters of the function get assigned the values supplied by the actual parameters in the call.
 * 3) The body of the function is executed
 * 4) Control returns to the point just after where the function was called.

SEE FIGURE 6.2 IN THE BOOK.

Using functions to organize your code
Functions can be used to simplify our program structure by making them more modular. We use functions to break up the complexity of our code into smaller subprograms which make sense on their own. We can do this with the greeting card by creating separate functions for creating the sky, house, garage, ground, tree, moon, snowflakes, etc.

Our resultant code might look something like:

from graphics import* from time import sleep import random

def create_light(window,x,y,color): light = Circle(Point(x, y), 2) light.setFill(color) light.draw(window) return light

def create_sky(win): sky = Rectangle(Point(0, 50), Point(200, 200)) sky.setFill(color_rgb(0, 10, 60)) sky.draw(win)

def create_house(win): #Roof of House roof= Polygon(Point(80, 120),Point(110, 110),Point(50, 110)) roof.setFill(color_rgb(30, 20, 30)) roof.draw(win)

#House house = Rectangle(Point(110, 110), Point(50, 50)) house.setFill(color_rgb(65, 75, 85)) house.draw(win) window = Rectangle(Point(100, 90), Point(80, 70)) window.setFill('lightblue') window.draw(win) window1 = Line(Point(90, 90), Point(90, 70)) window1.draw(win) window2 = Line(Point(100, 80), Point(80, 80)) window2.draw(win) door = Rectangle(Point(70, 70), Point(60, 50)) door.setFill('red') door.draw(win) doorknob = Circle(Point(62.25, 60), 1) doorknob.setFill('yellow') doorknob.draw(win)

def create_garage(win): #Garage garage = Rectangle(Point(150, 80), Point(110, 50)) garage.setFill(color_rgb(65, 75, 85)) garage.draw(win) garageroof = Polygon(Point(130, 90), Point(150, 80), Point(110, 80)) garageroof.setFill(color_rgb(30, 20, 30)) garageroof.draw(win) groof1 = Line(Point(130, 90), Point(150, 80)) groof1.draw(win) groof2 = Line(Point(150, 80), Point(110, 80)) groof2.draw(win) groof3 = Line(Point(110, 80), Point(130, 90)) groof3.draw(win) gdoor = Rectangle(Point(140, 70), Point(120, 50)) gdoor.setFill(color_rgb(30, 20, 30)) gdoor.draw(win) gwindow = Rectangle(Point(125.5, 70.25), Point(137.5, 77.5)) gwindow.setFill('lightblue') gwindow.draw(win)

def create_ground(win): ground = Rectangle(Point(0, 0), Point(200, 50)) ground.setFill('green') ground.draw(win) return ground

def create_tree(win): COLOR_TREE = color_rgb(120, 160, 56)

#Tree top = Polygon(Point(20,100), Point(25, 90), Point(15, 90)) top.setFill(COLOR_TREE) top.draw(win) middle = Polygon(Point(20, 90), Point(30, 80), Point(10, 80)) middle.setFill(COLOR_TREE) middle.draw(win) bottom = Polygon(Point(20, 80), Point(35, 60), Point(5, 60)) bottom.setFill(COLOR_TREE) bottom.draw(win)

trunk = Rectangle(Point(17.5, 50), Point(22.5, 60)) trunk.setFill('brown') trunk.draw(win)

def create_moon(win): sun = Circle(Point(50, 170), 15) sun.setFill('lightyellow') sun.draw(win)

def click_for_snow(win): #Snowflake numClicks = 10 snowflake = Circle(Point(130, 170), 1.75) snowflake.setFill('white') snowflake.draw(win) ####newflakes = [] for i in range(numClicks): p = win.getMouse c = snowflake.getCenter

dx = p.getX - c.getX dy = p.getY - c.getY

newsnow = snowflake.clone newsnow.move(dx, dy) newsnow.draw(win)

def create_lights(win): light1 = create_light(win,11,65,'red') light2 = create_light(win,25,65,'yellow') light3 = create_light(win,20,70,'green') light4 = create_light(win,15,84,'yellow') light5 = create_light(win,24,82,'green') light6 = create_light(win,20,93,'red')

lights = [] lights.append(light1) lights.append(light2) lights.append(light3) lights.append(light4) lights.append(light5) lights.append(light6) return lights

def create_snowman(win): snowman = [] head = Circle(Point(175, 72), 2) snowman.append(head) middle = Circle(Point(175, 65), 4) snowman.append(middle) last = Circle(Point(175, 55), 6) snowman.append(last) for snow in snowman: snow.setFill('white') snow.draw(win)

def create_wreath(win): ww = Circle(Point(65, 82), 8) ww.setFill('green') ww.draw(win) w = Circle(Point(65, 82), 4) w.setFill(color_rgb(65, 75, 85)) w.draw(win) lw = Circle(Point(65, 88), 1.5) lw.setFill('red') lw.draw(win) lw2 = Circle(Point(65, 77), 1.5) lw2.setFill('red') lw2.draw(win) lw3 = Circle(Point(60, 81), 1.5) lw3.setFill('red') lw3.draw(win) lw4 = Circle(Point(71, 82), 1.5) lw4.setFill('red') lw4.draw(win)

def create_moving_snow(win): newflakes = [] numClicks = 825 for i in range(numClicks): px = int(win.width * random.random) py = int(win.height * random.random) p = Point(px, py) newflake = Circle(p, 1.75) newflake.setFill('white') newflake.draw(win) newflakes.append(newflake) return newflakes

def move_snow_and_change_colors(win,newflakes,lights): colors = ['yellow', 'green', 'red', 'blue', 'orange'] for i in range(win.height): for flake in newflakes: flake.move(0, -random.random) for light in lights: coli = int(random.random * len(colors)) light.setFill(colors[coli])

sleep(0.025)

win = GraphWin("Season Greetings", 400, 400)
 * 1) Our program starts here
 * 1) Our program starts here

win.setCoords(0, 0, 200, 200)

create_sky(win) create_house(win) create_garage(win) ground = create_ground(win) create_tree(win) create_moon(win)

instructions = Text(Point(110, 140), "Click anywhere 10 times to make it snow!") instructions.setFill('red') instructions.setSize(7) instructions.draw(win)

win.getMouse instructions.undraw

click_for_snow(win)

instructions.setText("click again to see what happenes next!") instructions.draw(win) win.getMouse instructions.undraw
 * 1) Fading Stuff

ground.setFill('white')

lights = create_lights(win) create_snowman(win) create_wreath(win)

message= Text(Point(90,30), "Season Greetings!") message.setFill('red') message.draw(win)

newflakes = create_moving_snow(win) move_snow_and_change_colors(win,newflakes,lights)

instructions.setText("click again to close!") mag = message.getAnchor iga = instructions.getAnchor instructions.move(mag.getX - iga.getX + 20, mag.getY - iga.getY - 6) instructions.draw(win) win.getMouse win.close

Functions that modify parameters

 * Adopted from http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference

What we need to know:


 * 1) parameters are passed by value, which means the function receives a copy.
 * 2) the parameter that is passed in is actually a reference to a variable (but the reference is passed by value)
 * 3) some data types are mutable, but others aren't


 * If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight,
 * but if you rebind the reference in the method, the outer scope will know nothing about it
 * If you pass an immutable object to a method, you still can't rebind the outer reference, and you can't even mutate the object.

Some examples
List - a mutable type def try_to_change_list_contents(the_list): print('got', the_list) the_list.append('four') print('changed to', the_list)

outer_list = ['one', 'two', 'three']

print('before, outer_list =', outer_list) try_to_change_list_contents(outer_list) print('after, outer_list =', outer_list)

Output:

before, outer_list = ['one', 'two', 'three'] got ['one', 'two', 'three'] changed to ['one', 'two', 'three', 'four'] after, outer_list = ['one', 'two', 'three', 'four']

Now let's see what happens when we try to change the reference that was passed in as a parameter: def try_to_change_list_reference(the_list): print('got', the_list) the_list = ['and', 'we', 'can', 'not', 'lie'] print('set to', the_list)

outer_list = ['we', 'like', 'proper', 'English']

print('before, outer_list =', outer_list) try_to_change_list_reference(outer_list) print('after, outer_list =', outer_list)

Output: before, outer_list = ['we', 'like', 'proper', 'English'] got ['we', 'like', 'proper', 'English'] set to ['and', 'we', 'can', 'not', 'lie'] after, outer_list = ['we', 'like', 'proper', 'English']

String - an immutable type

def try_to_change_string_reference(the_string): print('got', the_string) the_string = 'In a kingdom by the sea' print('set to', the_string)

outer_string = 'It was many and many a year ago'

print('before, outer_string =', outer_string) try_to_change_string_reference(outer_string) print('after, outer_string =', outer_string)

Output: before, outer_string = It was many and many a year ago got It was many and many a year ago set to In a kingdom by the sea after, outer_string = It was many and many a year ago