Yesterday your programs ran straight through, top to bottom. Today they start
making choices — and every choice comes down to one question: is this True or
False?
Warm-up: from Day 1
Three quick ones before anything new. Try them without scrolling back to Day 1: pulling an idea out of memory is exactly what makes it stay there. Stuck for more than a minute? That’s worth knowing too — open the hint and carry on.
1. Predict all three lines, then run it.
item = " Notebook "
price = 3
print(f"[{item.strip()}]", price * 4)
print(20 // 6, 20 % 6)
print(type(20 / 5))Check your prediction
[Notebook] 12
3 2
<class 'float'>/ gives a float even when it divides evenly — 20 / 5 is 4.0.
2. Fix. This should print 1h 35m, and crashes instead.
minutes = "95"
print(f"{minutes // 60}h {minutes % 60}m")Check your fix
minutes = int("95")
print(f"{minutes // 60}h {minutes % 60}m")1h 35m"95" is text, and text can’t be floor-divided. Numbers that arrive as text —
from input(), from a file — need converting before any arithmetic.
3. Write. A receipt total arrives as the text "$12.50". Print it with a
10% discount, to two decimal places: 11.25.
total = "$12.50"Check your answer
total = "$12.50"
amount = float(total.replace("$", ""))
print(f"{amount * 0.9:.2f}")11.25Clean the text, convert it, then calculate: the same order as any messy input.
total.strip("$") works too.
Comparison operators
print(3 < 5)
print(3 > 5)
print(3 <= 3)
print(3 == 3) # equal to - two equals signs
print(3 != 3) # not equal to
age = 20
print(age >= 18)
print(type(age >= 18))= and == are different
= assigns a value; == asks a question. age = 18 sets the age. age == 18
checks it. Mixing them up is a rite of passage — Python catches it as a
SyntaxError in an if, which is more than most languages do for you.
Comparisons work on strings too, alphabetically by character code:
print("apple" < "banana")
print("Zoe" < "adam") # uppercase sorts before lowercase
print("apple" == "Apple")
print("apple".lower() == "Apple".lower())
# Python lets you chain comparisons, and it reads exactly as it looks.
score = 75
print(60 <= score < 90)That last line is genuinely nice: 60 <= score < 90 is one expression, and
score is evaluated once. Few languages allow it.
Combining conditions
and, or and not join conditions together. Python spells them as words,
not symbols.
age = 25
has_ticket = True
print(age >= 18 and has_ticket)
print(age >= 65 or has_ticket)
print(not has_ticket)
# and requires both; or requires at least one.
print(True and False)
print(True or False)
# Parentheses make mixed expressions readable.
is_free = (age < 12) or (age >= 65)
print(f"Free entry: {is_free}")and returns True only when both sides are true. or returns True when at
least one is. not flips whatever it is given.
Truthiness
Every Python value can be treated as a condition, not just True and False.
The rule is short: empty is false, everything else is true.
# These are all "falsy":
print(bool(0), bool(0.0), bool(""), bool([]), bool({}), bool(None))
# Everything else is "truthy":
print(bool(1), bool(-3), bool("hello"), bool(" "), bool([0]))This is why you will see if name: rather than if name != "": in real
Python. It reads as “if there is a name”, which is what you meant.
None is not False
None is Python’s “no value at all” — what a function returns when it returns
nothing. It is falsy, but it is not False, and it is not 0. Test for it
with is None, never with == None.
Short-circuiting
and and or stop as soon as the answer is settled. This is not a
micro-optimisation — it is a tool for writing safe conditions.
def loud(value):
print(" (checked)", value)
return value
print("First:")
result = loud(False) and loud(True) # second call never happens
print("Second:")
result = loud(True) or loud(False) # second call never happens
# Which is why this is safe even when the text is empty:
text = ""
print(len(text) > 0 and text[0] == "A")Before you write your own
Predict. Four lines — the last one has a trap in it.
budget = 50
spent = 42
print(spent < budget)
print(spent == 42 and budget > 100)
print(not spent)
print(bool(""), bool("0"))Check your prediction
True
False
False
False Truenot spent is False because 42 is truthy. And "0" is a string with one
character in it — not empty, so truthy — even though the number 0 is falsy.
Fix. This should print True on a Saturday or Sunday and False otherwise.
It’s Monday. Run it: what comes out isn’t even True or False.
day = "mon"
is_weekend = day == "sat" or "sun"
print(is_weekend)Check your fix
day = "mon"
is_weekend = day == "sat" or day == "sun"
print(is_weekend)FalsePython read the original as (day == "sat") or "sun". The left side is False,
so or moved on and gave back its right side — the string "sun", which is
truthy. Each side of an or has to be a whole condition on its own.
Password checker
Write a condition that decides whether a password is acceptable. It must be at
least 8 characters long and contain a digit. Print True or False — for
"hunter2000" that’s True. Then try "hunter2" and "hunterhunter", which
should both print False, for different reasons.
any(c.isdigit() for c in password) tells you whether any character is a
digit — you will understand that syntax fully on Day 4.
password = "hunter2000"
# Your code hereHint 1: the idea
Two separate yes/no questions, joined by and: is it long enough? Does it
contain a digit? Each question is one comparison you can write on its own line.
Hint 2: a first step
Answer the first question into a variable and print it:
long_enough = len(password) >= 8. Then do the same for the digit check using
the any(...) line above, and only then combine the two.
Show one solution
password = "hunter2000"
long_enough = len(password) >= 8
has_digit = any(c.isdigit() for c in password)
print(long_enough and has_digit)Naming the two halves before combining them is worth the extra lines: the final condition then reads as a sentence rather than a puzzle.
What you learned
==!=<><=>=produceTrueorFalse;=assigns.- Comparisons chain:
0 <= x < 10. and,or,notcombine conditions, and they short-circuit.- Empty values are falsy; everything else is truthy.
Nonemeans “no value”; test it withis None.