Welcome to DS2000 CS Practicum 5!This week we'll practice:
making good use of functions
Before we get to the actual exercise, a few reminders from last week
SyntaxError: invalid syntaxwhen using
ifstatements and logical operators
or. Solution: each statement separated by a logical operator must on its own make logical sense. For example, when we check if
n_beansis bigger than
0and smaller than
4, we cannot say
if n_beans > 0 and < 4:because
< 4on its own does not mean anything. Instead, we must say
if n_beans > 0 and n_beans < 4:, or skip using the logical operator altogether, like that:
if 0 < n_beans < 4:. In the latter case the whole expression is treated as one. Problem:
NameError: name 'XXXX' is not definedor
UnboundLocalError: local variable 'XXXX' referenced before assignment. Solution: It means you are using a variable that does not seem to exist. There are three popular reasons why you're getting this error (and a few less popular ones too!):
spelling. Make sure you spelled it correctly. Especially with long variable names it's easy to switch two letters around and not notice.
scope. Maybe you're trying to use a variable that you defined in your
main()function, but the function that throws the error does not know it (or vice versa). Consider this example:
def printer(x): # this function will refer to what it's given as x print(y) # so it doesn't know y at this point def main(): y = 2 printer(y) # we pass our variable y to print main()When we run it, we get
NameError: name 'y' is not definedin at
print(y)because our function
printer(x)refers to everything it's given as
x. order of execution. Consider this example:
def main(): x = 1 if x == 2: y = 3 else: print(y) main()Try running it. Why do we get an error? The spelling is fine and the scope is fine (same function), so what's the problem? capitalization. When you use
False, make sure to capitalize the first letter and not the others,
TRUEdon't mean anything!
UnboundLocalError: local variable 'XXXX' referenced before assignment. Solution: It means you are using a variable that exists somewhere.
Exercise 1: this is why functions are good.Last week we asked the user about speed and starting coordinates of two turtles. The most straightforward way to do it would look like this:
def main(): turtle_1_x = float(input('Please provide the X coordinate of turtle1 between -350 and 350: ')) while turtle_1_x < -350 or turtle_1_x > 350: turtle_1_x = float(input('Wrong value. Please provide the X coordinate of turtle1 between -350 and 350: ')) turtle_1_y = float(input('Please provide the Y coordinate of turtle1 between -250 and 250: ')) while turtle_1_y < -250 or turtle_1_y > 250: turtle_1_y = float(input('Wrong value. Please provide the Y coordinate of turtle1 between -250 and 250: ')) turtle_1_speed = float(input('Please provide the speed of turtle1 between 0 and 10: ')) while turtle_1_speed < 0 or turtle_1_speed > 10: turtle_1_speed = float(input('Wrong value. Please provide the speed coordinate of turtle1 between 0 and 10: ')) turtle_2_x = float(input('Please provide the X coordinate of turtle2 between -350 and 350: ')) while turtle_2_x < -350 or turtle_2_x > 350: turtle_2_x = float(input('Wrong value. Please provide the X coordinate of turtle2 between -350 and 350: ')) turtle_2_y = float(input('Please provide the Y coordinate of turtle2 between -250 and 250: ')) while turtle_2_y < -250 or turtle_2_y > 250: turtle_2_y = float(input('Wrong value. Please provide the Y coordinate of turtle2 between -250 and 250: ')) turtle_2_speed = float(input('Please provide the speed of turtle2 between 0 and 10: ')) while turtle_2_speed < 0 or turtle_2_speed > 10: turtle_2_speed = float(input('Wrong value. Please provide the speed coordinate of turtle2 between 0 and 10: '))It works, but it's a lot to look at and there's a huge chance you'll forget to replace the variable name somewhere while copying and pasting this code (I sure hope you didn't just type it out every time!).
Notice that every time we request user input we follow the same procedure:
Display a prompt for user to input a value between a minimum and a maximum value and save their response to a variable.
While the user is putting in a value that's outside of permitted range, display an error message, and show the prompt with the minimum and the maximum value again.
Rather than coping and pasting the code many times, we could have a single function to handle that. It will have the prompt, minimum, maximum, error message as arguments, it will handle the user interaction and after it gets an acceptable value from the user, it returns it. Now write this function:
def myinput(prompt, error, minimum, maximum): # result = float(input(prompt + ' between ' + str(minimum) ... # here comes more the magic with the while loop # and here more with displaying an error message and asking again return result
Now follow these steps:
Save this function in a file called
utils.py. Open test.py and then save (File > Save As ...; do not copy and paste because something weird happens with tabs and spaces) to the same folder as your
utils.pyand run it to verify that your function behaves in the way you would expect. Download ex5_1.py to the same folder and modify it so that it uses your
myinputfunction rather than handling user interaction in the
mainfunction. I hope you see that the code now is much easier to read and understand when we use functions properly!
In the previous example we covered the case with two turtles. What if we don't want to limit the user to only two turtles? Download ex5_2.py and have a look.
Run the code and see what it does. Use
#comments to explain what happens in line 41
for i in range(int(n_turtles)), line 44
turtles.append(t), line 47
for t in turtles:, and line 48
run(t). Fix Line 39
n_turtles = 3to ask the user how many turtles should be in the race. Then run the code to see if it worked. It did? Great! You probably noticed that the turtles cross the line and the game is not over. Modify the
gameoverfunction using the
for eachapproach so that the game is over when any of the turtles crosses the line.
Exercise 4: Extra creditDownload ex5_4.py and modify it so that it:
Asks the user how many turtles to create (at least 2).
In a for loop it asks the user for x, y, and speed of each turtle, then creates a turtle at those coordinates (use the
spawn(x, y, speed)function) has many turtles chasing the first turtle in the list correctly uses the
gameover()function to end the game when any of the turtles catches up with turtle 0.