Truthiness: any value can be a condition
Real data goes missing constantly: a form field left blank, a search that matched nothing, a counter still at zero. Checks for that kind of emptiness are so common that Python lets any value stand directly as a condition, and if name: is a line you will read in almost every Python codebase.
An if does not require a literal True or False. Python treats every value as truthy or falsy. The falsy list is short:
0and0.0- the empty string
"" None(Python's value meaning nothing here)False- empty containers (you will meet lists in unit 6,
[]is falsy too)
Everything else counts as True. So if name: reads as if name is not empty, which is exactly the Pythonic way to write it:
name = "" if name: print("hello", name) else: print("no name given")
Watch the trap: the string "False" is truthy, because the rule is about emptiness, not the text inside.
Values used directly as conditions
Neither if below contains a comparison. Each one tests a value on its own, and both of these values happen to be falsy: name is empty and count is zero.
name = "" if name: print("hello", name) else: print("no name given") count = 0 if count: print("count is", count) else: print("count is zero")
Output
no name given count is zero
Both else branches ran. The empty string counts as falsy, so if name: reads naturally as asking whether a name was supplied at all. The same applies to count, where zero is falsy and any other number, including a negative one, would have taken the first branch. That last detail is worth remembering, because if count: and if count > 0: are not the same test.
Nesting: an if inside an if
Branches can contain whole new if statements. Each level indents 4 more spaces:
if user == "ada": if pw == "secret": print("welcome") else: print("wrong password") else: print("unknown user")
Nesting expresses dependent questions: the password only matters once the user matched. If your questions are independent alternatives, a flat elif chain (lesson 4-1) reads better. Two levels of nesting is normal, four is a sign to reorganize.
Of the usual candidates, the truthy one is "0", the string containing a zero character.
For strings the rule is about emptiness rather than content. "0" holds one character, so it is non-empty and therefore truthy, even though it looks like the number zero. The genuinely falsy values are the number 0, the empty string "", and None.
This is exactly the trap that catches people reading text input. A form field containing "0" passes an if value: check, while a blank field does not, so a program that means to test a numeric value has to convert it first.
A login check is the standard example of dependent questions, since the password is only worth examining once the username has matched.
user = "ada" pw = "secret" if user == "ada": if pw == "secret": print("welcome") else: print("wrong password") else: print("unknown user")
Output
welcome
The outer if establishes that the user exists, and the inner if sits entirely inside that branch with its own else, so a wrong password is reported only for a known user. The outer else covers everyone else. Both values match here, so control reaches the innermost print.
Indentation is what encodes this structure. The inner statement is indented four spaces past the outer one, and its else lines up with the inner if rather than the outer one, which is what keeps the two decisions distinct.
Here is truthiness doing its real job. A form field arrived containing nothing but spaces, and the code substitutes a default rather than greeting an empty name.
name = " " name = name.strip() if not name: name = "guest" print(f"welcome, {name}")
Output
welcome, guest
Stripping is the step that matters, because " " is non-empty and therefore truthy, while the stripped result "" is falsy. Applying not to that falsy value yields True, so the body runs and replaces name with "guest". The print sits outside the if, so it runs either way and formats whatever name ended up in the variable, whether supplied or defaulted.