if/elif/else and Python truthiness

RoadmapsPython

Overview

Python evaluates an `if`/`elif`/`else` chain top-down and runs the FIRST block whose condition is truthy, then skips all remaining branches. Both `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 include: - `False` and `None` - Numeric zeros (`0`, `0.0`) - Empty sequences (`""`, `[]`) - Empty collections (`{}`, `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. A common trap is using separate `if` statements when you meant to use `elif`. This causes multiple branches to execute when conditions overlap: status = 404 if status >= 400: print('error') # Executes! if status == 404: print('not found') # Also executes! Another trap is writing multi-line blocks just to assign a single variable based on a condition: if config.get('debug'): level = 'DEBUG' else: level = 'INFO' This verbose pattern obscures intent and is replaced by inline conditional evaluation (covered fully in `ternary-expressions`). Finally, when checking a single variable against many exact values, long `elif` chains become hard to maintain: if status == 400: return 'Bad Request' elif status == 404: return 'Not Found' elif status == 500: return 'Internal Error' This anti-pattern is solved using structural pattern matching (covered fully in `match-case`).

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

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

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

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.

Continue learning

Previous: Primitive types: int, float, bool, str

Previous: Dynamic typing and type()

Next: Ternary expressions

Next: match-case statement

Next: for and while loops

Return to Python Roadmap