None & truthiness
Overview
Python evaluates an if/elif/else chain top-down and runs the FIRST block whose condition is truthy, then skips all remaining branches — elif and else are optional. status = 404 if status == 200: print('ok') elif status == 404: print('not found') else: print('other') Python's truthiness rules determine what counts as truthy or falsy without an explicit comparison. Falsy values: False, None, 0, 0.0, '' (empty string), [] (empty list), {} (empty dict), set(). Everything else is truthy. So if response: works when response is a non-empty list, and if not user: works when user is None. Think of truthiness as Python asking 'does this value carry meaningful content?' — zero-quantities and empty containers say no.
Truthiness lets you write concise guards (if items: instead of if len(items) > 0:). The danger is when 0 or '' are valid values that must NOT be treated as 'missing' — a naked truthiness check would silently skip them.
Where used: FastAPI route guards (if not current_user: raise 401), Pydantic field validators, CLI argument presence checks
Why learn this
- Writing correct guards in FastAPI handlers that distinguish None from 0 or an empty string
- Understanding why if value: can silently hide a valid 0 — the foundation of safe API input validation
Code walkthrough
items = []
count = 0
name = 'alice'
if items:
print('has items')
if count:
print('count nonzero')
if name:
print('has name')
print('done')
Focus: items (empty list) and count (zero) are falsy so their blocks are skipped; name ('alice') is truthy so only 'has name' prints before 'done'.
Common mistakes
- Using truthiness when 0 or '' are valid inputs: if count: returns False for count=0, silently skipping valid data. Fix: use explicit checks (if count is None:) when 0 is a meaningful value.
- Forgetting elif stops the chain: Using separate if statements instead of elif means multiple branches can execute. Use elif when conditions are mutually exclusive.
Glossary
- truthiness
- How Python decides if a value is considered true or false in an if-statement without you having to explicitly check. Example: `if items:` is True when `items` is a non-empty list and False when it is empty.
- falsy
- Values that Python automatically treats as false, such as zero, empty lists, or None. Example: `if not []:` evaluates to True because an empty list is falsy.
Recall questions
- Which values does Python treat as falsy?
- If the first branch of an if/elif chain matches, what happens to the remaining elif and else branches?
- When is using `if value:` unsafe?
- What is the difference between chaining elif vs using separate if statements?
Understanding checks
What will this code print?
`error`
Python evaluates an if/elif chain top-down and executes only the FIRST matching block. Since `404 >= 400` is true, it prints 'error' and skips the remaining branches, even though `status == 404` is also true.
This code is intended to use the `timeout` from the config, but falls back to 10 if missing. It fails when `timeout=0` is passed in (which is a valid setting). Why?
It evaluates truthiness, and `0` is falsy, so it incorrectly falls back to `10`.
Truthiness checks like `not timeout` treat `0` as falsy. When 0 is a valid meaningful value, you must use an explicit check like `if timeout is None:`.
Practice tasks
HTTP status classifier
Modify `classify_status(code)` to return 'success' for 2xx codes, 'client_error' for 4xx, 'server_error' for 5xx, and 'unknown' for anything else. Use if/elif/else.
Challenge
Config timeout guard
Write `get_timeout(config, default)` that returns `config['timeout']` when it is present, not None, and a positive integer. Return `default` in all other cases. Use explicit checks, not truthiness.