3 Conditional Control Flow

Learn how Python uses conditional control flow to make decisions, compare values, combine conditions, and organize nested or alternative execution paths.

Making a First Conditional Decision

Conditional control flow lets a Python program choose which statements to execute. A condition evaluates to a Boolean result, either True or False, and the selected indented block runs only when its condition is satisfied.

The basic pattern is an : write the keyword if, place a condition after it, add a colon, and indent the statements controlled by that condition. Python conventionally uses four spaces for each indentation level.

For example, a program can test whether an age is at least eighteen with the condition age≥18\text{age} \ge 18. If the condition is true, it can display an adult-access message; if it is false, the indented statement is skipped.

Takeaway: An if statement connects a Boolean condition to the block of code that should run when the condition is true.

Choosing Among Multiple Branches

A decision can contain several mutually exclusive branches. Begin with if, add one or more clauses for additional tests, and optionally finish with as the default branch.

Python checks the branches from top to bottom. It executes the block belonging to the first true condition, then skips the remaining branches. For example, a score can be classified by testing whether it is at least 9090, then at least 8080, and then at least 7070. A score of 8484 selects the second branch and receives a B.

Branch order is important when conditions overlap. Test a specific case before a broader case. For a number, test whether it equals zero before testing whether it is nonnegative; otherwise, zero will be selected by the broader condition first.

Takeaway: Use for additional alternatives and for a fallback, while placing restrictive tests before broad tests.

Comparing Values and Ranges

form conditions by relating values. Common examples include equality with ==, inequality with !=, less-than and greater-than comparisons, inclusive comparisons such as <= and >=, membership with in, and identity checks with is.

Do not confuse assignment, written as =, with value comparison, written as ==. For example, password == "python123" asks whether two values are equal, while password = "python123" assigns a value to the variable.

Use is primarily for identity checks such as value is None; use == when the question concerns whether two values are equal. Python also supports . The expression 18≤age<6518 \le \text{age} < 65 expresses the same range as testing 18≤age18 \le \text{age} and age<65\text{age} < 65 together.

Takeaway: Choose the operator that matches the question: value, order, membership, or object identity.

Combining Conditions Safely

combine conditions into a larger decision. Use and when every requirement must be satisfied, or when at least one alternative is enough, and not when a condition should be reversed.

For example, entry might require both an age condition and an identification condition. In logical form, the decision is age≥18\text{age} \ge 18 and has_id. Parentheses can clarify grouping when a condition combines several requirements, such as membership together with a balance test.

Python uses . It checks logical expressions from left to right and may stop as soon as the result is known. In an and expression, a false left-hand condition prevents the right-hand condition from being evaluated. In an or expression, a true left-hand condition prevents further evaluation.

This behavior can guard an operation that requires a prerequisite. Testing items before items[0] ensures that the first element is accessed only when the collection is not empty.

Takeaway: Combine conditions deliberately, use parentheses for clarity, and use short-circuiting to protect dependent operations.

Using in Conditions

Python applies when an object appears directly in a conditional context. Values treated as false include False, None, numeric zero, empty strings, and empty containers. Most other values are treated as true.

This makes direct tests concise. Testing username checks whether a username was supplied, while testing tasks checks whether a collection contains any elements. The form if not tasks: is therefore a clear way to handle an empty task list.

Direct checks are often preferable to explicit comparisons such as testing a string against "", because the intent is to ask whether a usable value is present.

Takeaway: Test values directly when presence or emptiness is the real question, and use not when the empty or false case should trigger the branch.

Structuring Nested Decisions

A conditional can contain another conditional, creating . The inner test is evaluated only after the outer condition is true. Each deeper block must be indented farther than the block that contains it.

For example, an entry decision might first check whether a person is at least eighteen. Only then does it check whether the person has a ticket. This structure supports different responses for being too young, lacking a ticket, or satisfying both requirements.

When the same response applies to several requirements, nesting can often be replaced by a combined condition such as age >= 18 and has_ticket. When each stage needs its own explanation, nesting may be clearer.

Deep nesting can reduce readability. Handle invalid or incomplete cases early, then keep the main path at a shallow indentation level. A function can return immediately for an empty order or an unpaid order before processing the successful case.

Takeaway: Use nesting for genuinely staged decisions, but simplify independent requirements and handle exceptional cases early when that improves readability.

Avoiding Conditional-Control-Flow Mistakes

Conditional code commonly fails because of small syntax or ordering mistakes. Use == for comparison rather than = for assignment. Put a colon after every if, , and condition, and indent all statements in the same block consistently.

Check branch order whenever conditions overlap. A broad test such as number≥0\text{number} \ge 0 placed before a more specific test such as number>10\text{number} > 10 makes the later branch unreachable for positive values. Reverse the order when the specific classification should take priority.

When debugging a conditional, ask three questions:

  1. What exact value does each condition produce: true or false?

  2. Which branch appears first that can match the current value?

  3. Are the colon, indentation, comparison operator, and logical grouping correct?

Takeaway: Correct syntax is necessary, but correct branch order and clear condition logic determine whether the program makes the intended decision.

A Practical Decision-Making Pattern

Conditional control flow follows a consistent pattern:

  • Use if to begin a decision.

  • Use for additional alternatives that should be tested only if earlier branches fail.

  • Use for the default action.

  • Build conditions with , , membership tests, identity checks, or direct .

  • Use to express ranges clearly, such as 0≤score≤1000 \le \text{score} \le 100.

  • Rely on when a later expression depends on an earlier prerequisite.

  • Use nested decisions when one choice should occur only after another succeeds.

  • Reduce excessive nesting by combining conditions or returning early from a function.

The central design question is: which cases are possible, and which one should be selected first? Writing those cases from the most specific or urgent to the broadest default produces clearer and more reliable Python programs.