lec-12
Tracing code involving decisions adds a new level of fun to the proceedings.
Let's do 2 examples.
def bladder_discomfort(trip_len):
level = ""
if trip_len > 4:
level = "mild"
elif trip_len > 7:
level = "painful"
elif trip_len > 10:
level = "critical"
else:
level = "normal"
return levelWhat does bladder_discomfort(11) return?snoo = "woo"
b = 10
zob = ""
if (len(snoo) > b or len(zob) > 0):
zob = snoo
snoo = snoo.upper()
else:
b = snoo.upper()
snoo = zob + str(b)
print(snoo)
print(b)
print(zob)
if ("o" in snoo):
print(snoo.replace("o", "x"))
else:
print(snoo.replace("o", "u"))
What is displayed when this code is run?
⦾ boolean-returning functions
⦾ branching boo-boo update
⦾ debugging
⦾ wishful coding
Task
Make a function northern(lat_deg) that returns True if lat_deg is a northern latitude and False otherwise.
Then use that function in another function symbol_for(lat_deg), that returns "N" if lat_deg is a northern latitude, and "S" otherwise.
Assumption!
lat_deg is an int guaranteed to be in -90 ... 90 - but no 0 allowed!
A northern latitude has a latitude > 0.
def northern(lat_deg: int) -> bool:
return lat_deg > 0Task
Make a function northern(lat_deg) that returns True if lat_deg is a northern latitude (and False otherwise).
....
🙋🏻♂️❓🙋🏻♀️Create a northern(lat_deg) function. It's got a one-line body.
Task
Make a function northern(lat_deg) that returns True if lat_deg is a northern latitude and False otherwise.
Then use that function in another function symbol_for(lat_deg), that returns "N" if lat_deg is a northern latitude, and "S" otherwise.
Let's show some different ways of finishing the second part of our task.
First, though - you try!
Task
Make a function northern(lat_deg) that returns True if lat_deg is a northern latitude (and False otherwise).
Then use that function in another function symbol_for(lat_deg), that returns "N" if lat_deg is a northern latitude, and "S" otherwise.
def northern(lat_deg: int) -> bool:
return lat_deg > 0
def symbol_for(lat_deg: int) -> str:
if northern(lat_deg):
return "N"
else:
return "S"
Easy to follow.
Is the else necessary?
Task
Make a function northern(lat_deg) that returns True if lat_deg is a northern latitude (and False otherwise).
Then use that function in another function symbol_for(lat_deg), that returns "N" if lat_deg is a northern latitude, and "S" otherwise.
def northern(lat_deg: int) -> bool:
return lat_deg > 0
def symbol_for(lat_deg: int) -> str:
if northern(lat_deg):
return "N"
return "S"
when you return, you leave the function!
Task
Make a function northern(lat_deg) that returns True if lat_deg is a northern latitude (and False otherwise).
Then use that function in another function symbol_for(lat_deg), that returns "N" if lat_deg is a northern latitude, and "S" otherwise.
def northern(lat_deg: int) -> bool:
return lat_deg > 0
def symbol_for(lat_deg: int) -> str:
symbol = ""
if northern(lat_deg):
symbol = "N"
else:
symbol = "S"
return symbol
Assign a variable a temporary dummy value, then re-assign in each branch.
Finally, return the variable.
Task
Make a function northern(lat_deg) that returns True if lat_deg is a northern latitude (and False otherwise).
Then use that function in another function symbol_for(lat_deg), that returns "N" if lat_deg is a northern latitude, and "S" otherwise.
def northern(lat_deg: int) -> bool:
return lat_deg > 0
def symbol_for(lat_deg: int) -> str:
if northern(lat_deg):
symbol = "N"
else:
symbol = "S"
return symbol
Assign value to a variable each branch.
Finally, return the variable.
Won't work in C++ or Java!
JP! Run this in PythonTutor to illustrate!
Task
Make a function northern(lat_deg) that returns True if lat_deg is a northern latitude (and False otherwise).
Then use that function in another function symbol_for(lat_deg), that returns "N" if lat_deg is a northern latitude, and "S" otherwise.
def northern(lat_deg: int) -> bool:
return lat_deg > 0
def symbol_for(lat_deg: int) -> str:
symbol = "S"
if northern(lat_deg):
symbol = "N"
return symbol
Choose a default value for a shared variable. Re-assign to that variable if necessary.
Finally, return that variable.
So which way is best?
Follow whoever is paying you.
Need to add one - and clarify another.
if lives_left > 0:
print("Continue?")
else lives_left <= 0:
print("Game over!")Bad Syntax
🙋🏻♂️❓🙋🏻♀️What's the problem? How do we correct it?
tank_empty = True
if tank_empty == True:
print("The tank...she be empty!")
else:
print("We got gas - let's roll!")if 1 <= dial <= 10:
print("The dial is pleased.")
if amount < 0:
print("Invalid amount.")
elif amount >= 0 and amount < 40:
print("Add some stuffs.")
else:
print("Yay! Free stuffs.")Bad Practices
if user_choice == "black" or "white":
print("Your world is very...plain.")we need to talk 'bout this
BTW - you don't have to memorize the numbers...they're just an arbitrary thing I made up!
if 1 <= dial <= 10:
print("The dial is pleased.")
This is called a chained comparison.
Most languages - particularly the ones you'll encounter for the rest of your degree - don't allow this sort of thing.
But Python does.
I did not know this until I started looking through your labs this weekend!
That being said, I'd be wary of getting too comfortable using it.
if a != b != c:
# do something
Not only will you NOT be able to use it in your future classes, but it has a few teeth. For example:
Do you think this means "do something if a, b, and c are all different"?
What if a and c are 3, but b is 1?
def discount(num_items: int) -> float:
'''Return discount depending on number of items purchased.'''
if num_items <= 1:
return 0
elif num_items <= 3:
return 0.1
elif num_items >3:
return 0.2
Why is our editor griping?
🙋🏻♂️❓🙋🏻♀️How do we correct this?
A (software) bug is an error in source code that causes that code to not do what it's supposed to do.
Debugging is the act of finding and removing bugs.
What's wrong?
The code violates one or more syntax rules and so the poor interpreter can't even run the code, because it can't interpret it.
How do I know I have one?
Oh, don't worry - your coding tools will let you know,
How should I feel when I see one?
Joyous, with perhaps a hint of embarrassment.
import sin from math
def skill_level(player: string) -> int
result = -1
very skilled = False or player == 'krom"
if len(player) =< 3:
result = 2
return result / sin result
def main:
skill_level("Mr. Tibbs")
main()Taste the rainbow!
How many can you find?
pro tip
if you can't find the error on the line being reported, look UP one line!
What's wrong?
The code, while syntactically correct, attempts to do something that will go when the code is run.
How do I know I have one?
Your terminal will vomit forth a traceback and a pall will settle upon you.
How should I feel when I see one?
Slightly confused until you read the traceback...after which, irritated.
def ask_for_skill_level() -> int:
return input("What's your skill level (1-10)? ")
def main():
skill_level = ask_for_skill_level()
if skill_level > 3:
print("Wow, you have mad skillz!")
else:
print("You are not worthy of my time.")
main()
What will happen no matter what the user enters?
Do NOT neglect the clues!
def ask_for_num_guests() -> int:
return int(input("How many guests? "))
def ask_for_num_spiders() -> int:
return int(input("How many spiders? "))
def main():
num_guests = ask_for_num_guests()
num_spiders = ask_for_num_spiders()
num_spiders_per_guest = num_guests // num_spiders
print(f"Each guest should get {num_spiders_per_guest} spiders.")
main()What will happen if the user enters 0 for the number of spiders?
What will happen if the user enters "none" for the number of guests OR spiders?
What's wrong?
The code is syntactically correct and runs without blowing up...but that thing it's supposed to do? Nope - it don't do that.
How do I know I have one?
When you run the code, something seems...off. Either a lot, or more terrifyingly, just a smidge.
How should I feel when I see one?
Dread, followed by an odd mix of despondency and grim determination.
MM_PER_CM = 100
def get_side_len_cm():
len_as_text = input("Length of side in cm? ")
return float(len_as_text)
def squarea(side_len):
return side_len ** 2
def display_result(side_len, area):
print(f"A {side_len}cm x {side_len}cm square has area {area:.1f}mm^2")
def main():
side_len_cm = get_side_len_cm()
side_len_mm = side_len_cm * MM_PER_CM
area = squarea(side_len_mm)
display_result(side_len_cm, area)
main()oops
dd
def extra_cashiers_avail(num_cashiers):
return num_cashiers > 1
def lines_are_too_long(len_longest_line):
return len_longest_line > 5
def is_weekend(day_of_week):
return day_of_week == "sa" or day_of_week == "su"
def should_open_checkout(dow, num_cashiers, len_longest_line):
return is_weekend(dow) and \
extra_cashiers_avail(num_cashiers) and \
lines_are_too_long(len_longest_line)
def main():
dow = "su"
longest_line = 7
num_cashiers = 4
if should_open_checkout(dow, longest_line, num_cashiers):
print("open another checkout")
main()
oops
def bladder_discomfort(trip_len):
level = ""
if trip_len > 4:
level = "mild"
elif trip_len > 7:
level = "painful"
elif trip_len > 10:
level = "critical"
else:
level = "normal"
return levelDesired behaviour of function:
You're going to encounter a lot of bugs in this field.
Welcome to your life.
Here is a laundry list of general strategies you can use to help you squash them bugs!
It's for a tiny plane with a forgetful pilot.
It asks how much fuel there is and whether the door is closed.
If there is 100L or more of fuel and the door is closed, it displays Ready for takeoff!; otherwise, it shows Don't take off yet, ya goof!
This technique is quite fun to use. It doesn't work for every problem - but it works for a lot of them.
def main() -> None:
pass
main()
Just having a bunch of code in your source file creates a whole bunch of global variables. This ain't good news. (Google "global variables are evil" if you're skeptical!)
pass is a useful bugger - it doesn't do anything...except not blow up
def main() -> None:
fuel_level = ask_for_fuel_level()
door_closed = ask_if_door_closed()
if plane_ready_for_takeoff(fuel_level, door_closed):
print("Ready for takeoff!")
else:
print("Don't take off yet, ya goof!")
main()
It should read like English...and solve the problem.
These are helper functions - functions we create to give a name to a part of our algorithm. We should use them - a LOT.
def ask_for_fuel_level() -> int:
return -1
def ask_if_door_closed() -> bool:
return False
def plane_ready_for_takeoff(fuel_level, door_closed) -> bool:
return False
def main() -> None:
fuel_level = ask_for_fuel_level()
door_closed = ask_if_door_closed()
if plane_ready_for_takeoff(fuel_level, door_closed):
print("Ready for takeoff!")
else:
print("Don't take off yet, ya goof!")
main()
stubs!
def ask_for_fuel_level() -> int:
return int(input("How much fuel do you have? "))
def ask_if_door_closed() -> bool:
return False
def plane_ready_for_takeoff(fuel_level, door_closed) -> bool:
return False
def main() -> None:
fuel_level = ask_for_fuel_level()
door_closed = ask_if_door_closed()
if plane_ready_for_takeoff(fuel_level, door_closed):
print("Ready for takeoff!")
else:
print("Don't take off yet, ya goof!")
fuel = ask_for_fuel_level()
print(fuel)
test that function - just a bit!
def ask_for_fuel_level() -> int:
return int(input("How much fuel do you have? "))
def ask_if_door_closed() -> bool:
response = input("Is the door closed (yes/no)? ")
return response == "yes"
def plane_ready_for_takeoff(fuel_level, door_closed) -> bool:
return False
def main() -> None:
fuel_level = ask_for_fuel_level()
door_closed = ask_if_door_closed()
if plane_ready_for_takeoff(fuel_level, door_closed):
print("Ready for takeoff!")
else:
print("Don't take off yet, ya goof!")
door_closed = ask_if_door_closed()
print (door_closed)
test that function!
def ask_for_fuel_level() -> int:
return int(input("How much fuel do you have? "))
def ask_if_door_closed() -> bool:
response = input("Is the door closed (yes/no)? ")
return response == "yes"
def plane_ready_for_takeoff(fuel_level, door_closed) -> bool:
SAFE_THRESHOLD = 100
return door_closed and fuel_level >= SAFE_THRESHOLD
def main() -> None:
fuel_level = ask_for_fuel_level()
door_closed = ask_if_door_closed()
if plane_ready_for_takeoff(fuel_level, door_closed):
print("Ready for takeoff!")
else:
print("Don't take off yet, ya goof!")
plane_ready_for_takeoff(99, True)
plane_ready_for_takeoff(100, False)test that function!
door_closed: T/F
fuel level boundaries: 99, 100, 101
try:
- T/99, T/100, T/101
- F/99, F/100, F/101
def ask_for_fuel_level() -> int:
return int(input("How much fuel do you have? "))
def ask_if_door_closed() -> bool:
response = input("Is the door closed (yes/no)? ")
return response == "yes"
def plane_ready_for_takeoff(fuel_level, door_closed) -> bool:
SAFE_THRESHOLD = 100
return door_closed and fuel_level >= SAFE_THRESHOLD
def main() -> None:
fuel_level = ask_for_fuel_level()
door_closed = ask_if_door_closed()
if plane_ready_for_takeoff(fuel_level, door_closed):
print("Ready for takeoff!")
else:
print("Don't take off yet, ya goof!")
main()