Today: variables, decomposition with functions, parameters
Preamble 1 - EarthSea
In with Wizard of EarthSea series .. each thing has its true name.
A magician calls a thing's true name, invoking the things power. Function calls work the same way!
- Last time: while loop
- Saw test, body, zero-iterations
- Today: infinite loop
- The body lines run, but make the test False
- The lines run but never finish
- May get error message: timed out - possible infinite loop
System notices code running for a long time, terminates it eventually
- Click the Bit "stop" button to stop the line hilighting
Like this (Nick demo using Wed functions):
Here's a more subtle bug. What is the problem here?
A: Easy typo to make - without parenthesis, the move function does not happen! Correct is
How To Call a Function
def many times - defines a function. Note that
each function has a name and body lines of code, like this "go_west" function:
1. Call by noun.verb
To "call" a function means to go run its code. One way to call a function in Python is the "object oriented" form, aka noun.verb. The bit functions look like that, e.g.
bit.left(), here "left" is the name of the function.
2. Call by name
The other way to call a function is just by using its name with parenthesis. For the above function named "go_west", code to call it looks like:
Both of these function-call styles are widely used in Python code.
What Does Function Call Do?
Say the program is running through some lines, which we'll call the "caller" lines. Then the run gets to the following function call line; what happens?
# caller lines
bit = Bit('5x5.world')
What this means simply is: (a) go run the lines inside the "go_west" function, suspend running here in the caller. (b) When go_west() is done, return to these caller lines and continue running with the next line. In other words, the program runs one function at a time, and function-call jumps over to run that function.
Decomposition - Program and Functions
- "Decomposition" - just starting today
- A program is divided into functions
- Each function takes on part of the problem
- "Divide and Conquer", class strategy, works great with code
- Next example we'll divide the problem into 2 functions
Fill World Blue Program
The whole program does this: bit starts at the upper left facing south. We want to fill the whole world with blue, like this
1. - Decompose fill_row_blue() "helper" function
First we'll decompose out a fill_row_blue() function that just does 1 row. Work on that function first.
This is a "helper" function - solves a smaller sub-problem.
Function Pre/Post Conditions
- Fitting multiple functions together
- Think about their pre/post conditions
- Pre - precondition of function
state of world before it runs
- Post - postcondition after it runs
state of world after it's finished
- Pre/Post make the "contract" of function - what it does
What it gets to assume when it is called
What it promises to provide
Look at fill_row_blue() Function
- Pre: bit is at left edge facing south
- Post: the horizontal row is all blue, bit is back at the start location and direction
- Convention: it's not required, but a post condition where bit returns to its original location is simple, so that's what we have here.
- We have this function that "solves" one row
- With the Run button .. we can test it on its own
- See the pre/post conditions at work
- Now comes the magic step...
2. Write fill_world_blue()
- Now write the fill_world_blue() function to solve the whole world
- Make a drawing to guide thinking
- Mindful of pre/post conditions
Function Call - A Great Deal!
- Write the code for fill_world_blue()
- Key Idea: call fill_row_blue() to solve that sub-problem
- Like you're the boss - do what I say!
- Think about its pre/post conditions when calling
- Questions: how are you going to fill that first row? later rows?
- Sketch the state of the world to think about progress
- Try using "End State" checkbox to skip to end-state output
- Start with 2 rows, then generalize to do all the rows
Variables - A Little
A variable stores a value for the code. Variables are set up with a single equal sign
=. Later appearances of that variable retrieve the stored value. Here's a little example:
color = 'red'
This paints 2 squares 'red', or whatever value was assigned to color on the first line.
Suppose we want to fill the world with color stripes like this
- Q: how to modify fill_row_blue() to paint 'green'?
- Q: how to modify fill_row_blue() to paint 'red'?
- The code is the same, but the 2 paint() calls
- Add a parameter named 'color'
- Function code assumes the correct value is in the parameter
- A parameter is like a variable, holding the passed value
- Code in the function uses color instead of 'blue'
- We have parameterized the function, it can paint whatever color is passed in
- Where does color come from?
- From the caller, shown below
New with parameter: fill_row_color():
def fill_row_color(bit, color):
bit.paint(color) # key line: use parameter
Function Call Syntax With Parameter
Call fill_row_color() with 'green':
1. Parameters match up by position, commas between parenthesis
2. Look at the Cases Menu w/ Run button .. shows this in action
Write Code For - stripe_world()
- Call fill_row_color() for each row
- "Pass in" color parameter like this
- Parameters match up by position
- Think about pre/post as before to call helper function
- This is our first day of decomposition
- Calling a helper function is very handy
- (Issue about leftover row next lecture)
Bit Beloved Program
Look at the problem statement. We'll work though solving this in lecture.
- Work on (a) first, then use it for (b)
- Use a variable to store the beloved color for later lines
color = bit.get_color()
- Make a Drawing to think about algorithm steps
- Think about possible cases a code-line may confront
- 1. beloved_row
- 2 cases: move to painted square, move to un-painted square
- 2. beloved_spiral
- Diagram out the problem
- First do lines not in loop (Run button works with this form)
- Nick does it or students do it
- Last line inside while loop .. goes to loop-test at top
- Demo: use step button, look at how call of beloved_row() works
Call goes into beloved_row(), returns to beloved_spiral() when done
- Case-4: example of an edge case
That's a lot to take in for one day. We'll work more examples Monday.