Skip to content

Conditionals & Logical Branching

In programming, we rarely want to execute every single line of code in every situation. Conditionals allow our programs to make decisions, essentially asking “If this is true, do that; otherwise, do something else.”

This chapter moves beyond the basic syntax to explore how Python evaluates truth, how it optimizes logical checks, and how to write clean, idiomatic branching logic.


1. The Foundation: Truthy and Falsy Values

Section titled “1. The Foundation: Truthy and Falsy Values”

In Python, every object has an inherent boolean value. You don’t always need a comparison (like x == 10) to trigger an if statement.

An object is Truthy if it evaluates to True in a boolean context. An object is Falsy if it evaluates to False.

By default, most objects are Truthy. Only a specific few are Falsy:

  • Constants: None and False.
  • Zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1).
  • Empty sequences and collections: '' (empty string), () (empty tuple), [] (empty list), {} (empty dict), set() (empty set).
truthy_falsy.py
def check_truth(value):
if value:
print(f"'{value}' is Truthy")
else:
print(f"'{value}' is Falsy")
check_truth("Hello") # Truthy
check_truth("") # Falsy
check_truth(42) # Truthy
check_truth(0) # Falsy

The basic structure of a conditional block allows for multiple independent checks.

  1. if: The entry point. Must come first.
  2. elif (Optional): Short for “else if.” Runs only if the previous conditions were False. You can have zero or many elif blocks.
  3. else (Optional): The “catch-all” fallback. Runs only if all previous conditions were False.
grading.py
score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
print(f"Your grade is {grade}")

It is critical to remember that Python evaluates an if-elif-else chain from top to bottom. As soon as it finds one condition that is True, it executes that block and skips the entire rest of the chain, even if later elif conditions would also be True.


We often need to combine multiple conditions into a single decision.

Both conditions must be True.

if age >= 18 and has_id:
print("Entry allowed")

At least one condition must be True.

if is_vip or has_ticket:
print("Entry allowed")

Flips the boolean value.

if not is_banned:
print("Entry allowed")

4. Under the Hood: Short-Circuit Evaluation

Section titled “4. Under the Hood: Short-Circuit Evaluation”

Python is efficient. When evaluating logical expressions, it stops as soon as the result is mathematically certain.

  • A and B: If A is Falsy, the whole expression must be False. Python will not even look at B.
  • A or B: If A is Truthy, the whole expression must be True. Python will not even look at B.

This allows you to write “Guard” logic in a single line without crashing your program.

short_circuit_guard.py
# If denominator is 0, the first part is False.
# Python skips the division entirely, preventing a ZeroDivisionError.
if denominator != 0 and (numerator / denominator) > 10:
print("High ratio!")

5. Conditional Expressions (The Ternary Operator)

Section titled “5. Conditional Expressions (The Ternary Operator)”

For simple assignments based on a condition, Python offers a concise one-line syntax.

Syntax: variable = [value_if_true] if [condition] else [value_if_false]

ternary.py
status = "Adult" if age >= 18 else "Minor"

Detailed Explanation: While this is elegant, avoid nesting ternary operators (e.g., a if b else c if d else e). This makes code incredibly hard to read and debug. If the logic is complex, stick to a standard if-else block.


6. Best Practices: Guard Clauses vs. Nesting

Section titled “6. Best Practices: Guard Clauses vs. Nesting”

Deeply nested if statements are a common sign of “code smell.” They make the logic difficult to follow (the “Arrow Anti-pattern”).

if user.is_active:
if user.has_permission:
if record.is_unlocked:
edit_record(record)

By checking for “failure” conditions early and exiting, we keep the main logic at the top level.

guard_clauses.py
if not user.is_active:
return "User is inactive"
if not user.has_permission:
return "Permission denied"
if record.is_locked:
return "Record is locked"
# Main logic is now clean and clear
edit_record(record)

How does the computer actually “skip” code? When Python compiles your script to Bytecode, it uses jump instructions.

If you inspect the bytecode of an if statement (using the dis module), you will see instructions like POP_JUMP_IF_FALSE. The Python Virtual Machine (PVM) checks the value on the stack; if it’s False, it changes the “Instruction Pointer” to a different line number further down, effectively leaping over the block of code.