delivery_hour = 21
print(delivery_hour < 22) # before curfew?
print(delivery_hour == 22) # exactly at curfew?True
False
Programming with Python
Overnight the city banned delivery after 22:00. Your app can no longer just say yes to every order. Today the code starts making decisions, repeating work over every order, and tidying up Kevin’s menu.
. . .
(Kevin’s fix: “we just deliver yesterday’s orders the next morning.” A lawyer disagreed.)
A comparison asks a question and answers with a boolean: True or False, the bool type you met last week:
delivery_hour = 21
print(delivery_hour < 22) # before curfew?
print(delivery_hour == 22) # exactly at curfew?True
False
Six operators, all returning True or False:
< less than · > greater than<= at most · >= at least== equal · != not equal. . .
= assigns a value; == compares two values. Mixing them up is the classic first-week bug.
and, or, not glue booleans together:
is_weekday = True
before_curfew = 21 < 22
print(is_weekday and before_curfew) # both must be TrueTrue
. . .
and needs both sides true; or needs at least one; not flips it.
if: do something only whenAn if runs its indented block only when the condition is True:
delivery_hour = 21
if delivery_hour < 22:
print("Open — send the courier.")Open — send the courier.
. . .
The indentation (4 spaces) is what marks the block. Python is strict about it.
if / else: two pathselse catches every case the if missed:
delivery_hour = 23
if delivery_hour < 22:
print("Open — send the courier.")
else:
print("Curfew — kitchen closed.")Curfew — kitchen closed.
if / elif / else: a ladderMore than two cases? Stack elif branches. Reward loyal customers by tier:
past_orders = 8
if past_orders >= 20:
tier = "Gold"
elif past_orders >= 5:
tier = "Silver"
else:
tier = "Bronze"
print(tier)Silver
Kevin rewrote the tier ladder “to keep the common case on top”. A customer with 25 past orders walks in. Which tier do they get?
past_orders = 25
if past_orders >= 5:
tier = "Silver"
elif past_orders >= 20:
tier = "Gold"
else:
tier = "Bronze"
print(tier)a) Gold b) Bronze c) Silver
. . .
Predict first. Commit to an answer before the next slide.
c) Silver — Python checks branches top to bottom and takes the first True one. 25 >= 5 is already True, so the Gold branch is never even looked at. Order your ladder from strictest to loosest.
past_orders = 25
if past_orders >= 5:
tier = "Silver"
elif past_orders >= 20:
tier = "Gold"
else:
tier = "Bronze"
print(tier)Silver
. . .
(One misplaced elif and Kevin demotes every VIP.)
The curfew is 22:00. An order comes in at exactly 22:00. What prints?
delivery_hour = 22
print(delivery_hour < 22)a) False b) True c) Error
. . .
Predict first. Commit to an answer before the next slide.
22 < 22a) False — < is strict. 22 is not less than 22, so at 22:00 sharp the kitchen is already closed. Use <= when the boundary should count.
delivery_hour = 22
print(delivery_hour < 22)False
Kevin totals the day’s orders by hand, one print per order:
print("Falafel Wrap")
print("Pad Thai")
print("Miso Ramen")Falafel Wrap
Pad Thai
Miso Ramen
. . .
Three lines for three items. A hundred orders? A hundred lines. There is a better way.
for: one step for every itemA for loop runs its block once for each item in a list:
menu = ["Falafel Wrap", "Pad Thai", "Miso Ramen"]
for item in menu:
print(item)Falafel Wrap
Pad Thai
Miso Ramen
. . .
item is the loop variable. It takes each value in turn, and the name is yours to choose.
Start a total at 0, then add each item as the loop visits it:
prices = [5.00, 3.50, 6.50]
total = 0
for price in prices:
total = total + price
print(total)15.0
. . .
After the loop, total holds the sum. This is how you replace Kevin’s hand-counted dashboard.
range(): count without a listrange(n) counts from 0 up to, but not including, n:
for i in range(3):
print(i) # ping the courier's phone 3 times0
1
2
. . .
Three passes: 0, 1, 2. (It stops before 3 — a beginner’s favorite surprise.)
range() with two and three argumentsrange(start, stop): begin at start, stop before stoprange(start, stop, step): jump by step each timeprint(list(range(2, 5))) # delivery windows 2, 3 and 4 o'clock
print(list(range(0, 10, 3))) # every 3rd order gets a flyer: 0, 3, 6, 9[2, 3, 4]
[0, 3, 6, 9]
A string is a sequence too, and a for loop walks it character by character:
for letter in "Pad":
print(letter)P
a
d
A list comprehension is a for loop compressed into one line that builds a list:
doubled = [n * 2 for n in [4, 5, 6]]
print(doubled)[8, 10, 12]
. . .
Just a taste. Session IV gives comprehensions their proper treatment. For now: recognize the shape.
print run?The print is not indented. What does this show?
total = 0
for n in [10, 20]:
total = total + n
print(total)a) 10 b) 10 then 30 c) 30
. . .
Predict first, then turn the page.
printc) 30 — print sits outside the loop, so it runs once, after the loop finishes, showing the final total. Indent it and it would print on every pass. Indentation decides what repeats.
total = 0
for n in [10, 20]:
total = total + n
print(total)30
while: repeat as long asA while loop repeats as long as its condition stays True. MunchCorp just undercut you. Cut your price each round until you drop below their price:
price = 10.00
rounds = 0
while price >= 7.00:
price = round(price * 0.8, 2) # 20% off each round
rounds = rounds + 1
print(rounds, price)2 6.4
. . .
Two rounds and you’re under 7.00. (The lab’s price war against MunchCorp is your boss fight tonight.)
Every pass must nudge the condition closer to False: here the price shrinks, so the loop is guaranteed to end.
. . .
If nothing changes, the condition never flips and the loop runs forever:
# ⚠️ NEVER run this — it never stops, and freezes the browser tab
count = 1
while count > 0:
count = count + 1 # count only grows — condition stays True forever. . .
An endless while will freeze your marimo tab. Always check that something inside the loop changes the condition.
break: an early exitbreak jumps out of a loop immediately, handy with while True:
count = 0
while True:
count = count + 1
if count == 3:
break
print(count)3
. . .
The loop would run forever, but break stops it the moment count hits 3.
Kevin typed the daily special IN ALL CAPS with stray spaces. Strings have methods that return a cleaned-up copy:
raw = " miso ramen "
print(raw.strip()) # drop outer spaces
print(raw.strip().title()) # then Capitalise Each Word
print("special".upper()) # SHOUTmiso ramen
Miso Ramen
SPECIAL
. . .
Methods can be chained left to right: raw.strip().title().
.strip() drops spaces; .rstrip("!") drops trailing !. Chain them to fix Kevin’s shouting:
print("SALE!!!".rstrip("!")) # SALE
print("SALE!!!".rstrip("!").title()) # SaleSALE
Sale
. . .
The original string is never changed — each method hands back a new one.
What does this print?
print(" MOIN ".strip().lower())a) MOIN b) moin c) moin
. . .
Predict first, then reveal.
" MOIN ".strip().lower()b) moin — .strip() removes the outer spaces, then .lower() lowercases the result. Chained methods run left to right, each acting on the previous one’s output.
print(" MOIN ".strip().lower())moin
while loop. . .
Download your .py before you leave. Closing the tab without downloading loses your work, and downloading is exactly how you hand in the checkpoints.
if / elif / else run the first true branch: test the strictest condition firstfor repeats over every item (accumulator: start at 0, add each); while repeats until its condition flips, and something inside must move it there.strip(), .title(), .upper(), .rstrip("!")) return a cleaned copy, and chain left to right. . .
Next time — Episode 3: Kevin has pasted the same receipt code 14 times, and one small change now takes him an afternoon. We bring in functions to the rescue.
. . .
Nothing new here, but these are still great books to start with!
. . .
For more, see the literature list of this course.