If/Elif/Else Statements

7 min read

Tests are decisions in disguise. If the status code is 200, mark the case passed; else if it's 5xx, retry; else fail loudly. Python expresses those decisions with if, elif, and else — three keywords, no braces, no parentheses, and a hard rule about indentation that surprises every newcomer. This lesson covers the syntax, the comparison and logical operators, the truthy/falsy quirks, the ternary form, and in — enough conditional fluency to classify any API response or test result.

The basic shape

status_code = 200
 
if status_code == 200:
    print("Success")
elif 400 <= status_code < 500:
    print("Client error")
elif status_code >= 500:
    print("Server error")
else:
    print("Unknown status")

Read each piece:

  • if condition: — the keyword if, an expression that evaluates to True or False, then a colon. The colon is mandatory; forgetting it is a SyntaxError.
  • elif condition: — short for "else if". JavaScript and Java use else if; Python uses one word, elif. Always check this first when porting a JS snippet.
  • else: — runs when nothing above matched. Optional but usually a good idea so unhandled cases are visible.
  • The colon ends every line that opens a block. if, elif, else all need it.

Notice what's not there: no parentheses around the condition, no curly braces around the body. if (status_code == 200) { is JavaScript/Java; if status_code == 200: is Python.

Indentation is the syntax

The body of each branch is indented. Python uses indentation the way other languages use { }. The convention is four spaces per level — every Python tutorial, every linter, every PR review expects four. VS Code with the Python extension inserts four spaces when you press Tab.

if status_code == 200:
    log_success(status_code)        # 4 spaces — this line is in the if body
    record_metric("response.ok")    # 4 spaces — also in the if body
print("Done")                       # 0 spaces — this line is OUTSIDE the if

Three rules to internalise on day one:

  1. Be consistent within a file. Pick four spaces and stick with them.
  2. Don't mix tabs and spaces. Python 3 raises TabError if you do. Modern editors handle this automatically — leave the defaults alone.
  3. Indent or you've changed meaning. A line with no indent is outside the if. The compiler in Java doesn't care if you indent; in Python the indent is whether the line belongs to the block.

Comparison operators

Same as JavaScript and Java — these all return True or False:

OperatorMeaningExampleResult
==Equal200 == 200True
!=Not equal200 != 404True
>Greater than1.5 > 1.0True
<Less than100 < 99False
>=Greater or equal200 >= 200True
<=Less or equal200 <= 200True

Python has one nice extra — chained comparisons:

if 400 <= status_code < 500:
    print("Client error")

400 <= status_code < 500 is the natural reading of "is the value in this range" and is equivalent to 400 <= status_code and status_code < 500. JavaScript and Java don't have this — if (400 <= x < 500) parses but means something else there.

Logical operators — words, not symbols

This is the big break from C-family languages. Python uses English words for logical operators:

if status_code == 200 and response_time < 2000:
    print("Fast success")
 
if status_code >= 500 or status_code == 0:
    print("Server problem or no response at all")
 
if not is_authenticated:
    print("Login required")
PythonJavaScript / Java
and&&
or||
not!

Writing && in Python is a SyntaxError. There is no ||. Reach for the words.

Python's and and or short-circuit the same way as && / ||or stops at the first truthy value, and stops at the first falsy. Cheap left-side checks belong on the left.

Truthy and falsy values

Python evaluates non-boolean values as truthy or falsy in a boolean context (if, while, and, or):

FalsyFalse, 0, 0.0, "" (empty string), [] (empty list), {} (empty dict), None.

Truthy — everything else.

results = []
if results:
    print(f"{len(results)} results")
else:
    print("No results yet")     # this prints — empty list is falsy

That collapses what would be if (results !== null && results.length > 0) in JavaScript into just if results:. Use it carefully: if count: is False when count == 0, which is fine if zero counts as "nothing" but wrong if zero is a valid value you care about.

The ternary expression — different shape

Python's one-line conditional puts the value first, condition in the middle:

result = "PASS" if passed else "FAIL"

Read it left-to-right: "result is PASS if passed else FAIL". JavaScript and Java write passed ? "PASS" : "FAIL"; Python's order is deliberately closer to English.

A QA example — labelling a response by status code:

status_code = 503
label = "ok" if status_code < 400 else "error"
print(label)    # "error"

Use the ternary for short, simple choices. Once you'd need parentheses to make sense of it, switch to a regular if/else block.

The in operator — membership check

in checks if a value appears inside a sequence (string, list, tuple, dict, set):

browser = "Firefox"
if browser in ["Chrome", "Firefox", "Safari"]:
    print(f"{browser} is supported")
 
method = "POST"
if method in ("GET", "POST"):
    print("Standard method")
 
email = "alice@test.com"
if "@" in email:
    print("Looks like an email")

in collapses what would be a long if x == "Chrome" or x == "Firefox" or x == "Safari" chain into a single line. not in is the negation: if browser not in supported_browsers:.

For dicts, in checks keys: if "timeout" in config:.

A QA example — classifying an API response

A function that classifies a response by its status code and latency:

def classify(status_code: int, response_time_ms: int) -> str:
    if status_code == 0:
        return "no-response"
    if status_code >= 500:
        return "server-error"
    if 400 <= status_code < 500:
        return "client-error"
    if status_code in (200, 201, 204) and response_time_ms < 500:
        return "fast-success"
    if status_code in (200, 201, 204) and response_time_ms < 2000:
        return "slow-success"
    if status_code in (200, 201, 204):
        return "very-slow-success"
    return "unexpected"
 
print(classify(200, 320))    # "fast-success"
print(classify(503, 5000))   # "server-error"
print(classify(404, 80))     # "client-error"
print(classify(0, 0))        # "no-response"

Notice how each branch returns early — once a category matches, the function exits. This pattern (a chain of if … return) reads cleanly and avoids deeply nested else ladders.

The decision tree, drawn

The chart traces the same logic the function above implements. Branches at each diamond return early; only the bottom path falls through to "unexpected."

⚠️ Common mistakes

  • else if instead of elif. else if is JavaScript and Java. Python rejects it as a SyntaxError. Always one word: elif.
  • Forgetting the colon. if status_code == 200 (no colon) raises SyntaxError: expected ':'. Every if, elif, and else line ends with :.
  • Mixing tabs and spaces. A file that looks indented can fail with TabError: inconsistent use of tabs and spaces. Pick four spaces and let your editor convert tabs. Most pain disappears the moment you settle this.

🎯 Practice task

Build a response-time classifier. 20-30 minutes.

  1. Create classify_response.py and define a function classify(status_code, response_time_ms) returning a string label.
  2. Implement these rules with a chain of if / elif / else:
    • status_code == 0 → "no-response"
    • status_code >= 500 → "server-error"
    • 400 ≤ status_code < 500 → "client-error"
    • 2xx and response_time_ms < 500 → "fast-success"
    • 2xx and 500 ≤ response_time_ms < 2000 → "slow-success"
    • 2xx and response_time_ms ≥ 2000 → "very-slow-success"
    • otherwise → "unexpected"
  3. Below the function, call classify six times with different inputs and print each result. Cover at least one of each label.
  4. Run python classify_response.py and confirm the output.
  5. Add a final block: read a status code from input(), convert with int(), classify it, and print the label. Try entering 200, 404, 503, and 0.
  6. Stretch: add a single combined condition using and and chained comparison: if status_code in (200, 201, 204) and 500 <= response_time_ms < 2000. Replace the two-step nested check with the single line. Confirm the behaviour is identical and the code reads more cleanly.

You can now branch on any condition Python supports. The next lesson moves on to loops — for, while, and Python's beloved range().

// tip to track lessons you complete and pick up where you left off across devices.