# Control Flow, Conditional Statements, and Loops

> Chapter 2 of the Courseiva PYTHON-PCAP curriculum — https://courseiva.com/learn/python-pcap/control-flow-and-loops

**Official objective:** 1.2 — Use if, else, elif, while, and for loops to control program flow.

## Introduction

How do you make a Python program do one thing if a condition is true and another if it's false? That's the exact problem control flow solves. It's the most fundamental skill you will use in every single program you write for the PCAP-31-03 exam because it gives your code the ability to make decisions and repeat actions automatically.

## The Recipe Flow Chart Analogy

Have you ever tried to bake a cake without a recipe and ended up with a sugary mess? 

To bake a perfect chocolate cake, you follow a recipe. The recipe isn't just a list of ingredients; it's a sequence of instructions, often with decisions and repetitions. You check if you have eggs. If you do ('if'), you crack them. If you don't ('else'), you go to the shop. You whisk the batter 'until' it is smooth — that's a repetition, or a loop. You mix in chocolate chips 'for every' cup of flour — another loop. Each step depends on the previous one, and the whole process flows from start to finish, with branches for different conditions. The recipe is your control flow. The 'if' statements are your ingredient checks. The 'while' (until smooth) and 'for' (for each cup) are your loops. This is exactly how a Python program works. The code is your recipe, and the conditions and loops dictate the order in which the instructions are executed, preventing a sugary mess of a program.

## Core explanation

Control flow is the order in which a computer executes the statements in a program. Without it, every line of code runs exactly once, from top to bottom, one after the other. That's fine for a simple calculator, but most programs need to make choices and repeat tasks. This is where conditional statements and loops come in, and they form the backbone of how we control the program's flow.

Let's start with **conditional statements**. These let your program make decisions based on whether a condition is 'true' or 'false'. In Python, the main tools for this are `if`, `elif`, and `else`. Think of `if` as the primary fork in the road. You give it a test, like a boolean expression (an expression that evaluates to either `True` or `False`). If the test passes (is `True`), the code block underneath the `if` runs. If it fails (is `False`), the program skips that block.

For example:
```python
temperature = 30
if temperature > 25:
    print("It's a hot day!")
```
Here, `temperature > 25` is the condition. It checks if the variable `temperature` (which holds the value 30) is greater than 25. Since it is, the `print` statement runs. If the temperature were 20, the code inside the `if` block would be completely ignored.

Sometimes you need a plan B. That's `else`. It's the catch-all that runs when the `if` condition is `False`.
```python
temperature = 15
if temperature > 25:
    print("It's a hot day!")
else:
    print("It's not a hot day.")
```
Now, if the temperature is not greater than 25, the program automatically runs the `else` block. This creates two distinct paths the code can take.

Real-life decisions are rarely just two-way. You might need to check multiple conditions. That's where `elif` (short for 'else if') steps in. It allows you to chain multiple conditions together, checking them one by one until one is `True`. Once it finds a true condition, it runs the corresponding block and then skips the rest of the `elif` and `else` blocks.

```python
temperature = 22
if temperature > 25:
    print("It's a hot day!")
elif temperature > 15:
    print("It's a warm day.")
else:
    print("It's a cold day.")
```
Here, the first condition (`temperature > 25`) is `False`. Python moves to the `elif` and checks `temperature > 15`. This is `True` (because 22 > 15), so it prints "It's a warm day." It then completely ignores the `else` block. This is perfect for handling multiple, exclusive scenarios.

Now, what about doing something over and over? That's what **loops** are for. Why do we need them? Imagine you want to print the numbers 1 to 100. Without loops, you'd have to write 100 `print()` statements. With a `for` loop, you write two lines. Loops automate repetition, making your code shorter, less error-prone, and more powerful.

There are two main types of loops in Python: `for` loops and `while` loops.

A **`for` loop** is used to **iterate** (go through) a sequence. A sequence is an ordered collection of items, like a list (a collection of values in square brackets), a string (a sequence of characters), or a range of numbers. The `for` loop picks each item from the sequence, one at a time, and assigns it to a variable you name. The loop's code block runs once for each item in the sequence.

```python
for number in [1, 2, 3, 4, 5]:
    print(number * 2)
```
This will print:
```
2
4
6
8
10
```
The loop variable `number` takes the value 1, runs the `print`, takes the value 2, runs the `print`, and so on until the list is exhausted. A `for` loop is perfect when you know exactly how many times you want to loop because you are iterating over a known collection of things.

The **`while` loop** is different. It doesn't iterate over a sequence. Instead, it keeps repeating a block of code `while` a given condition is `True`. It's like a bouncer at a club: "Keep letting people in while there is space inside." The moment the condition becomes `False`, the loop stops. You use a `while` loop when you don't know exactly how many repetitions are needed, but you know the condition for stopping.

```python
count = 0
while count < 5:
    print("Count is:", count)
    count = count + 1
```
This will print:
```
Count is: 0
Count is: 1
Count is: 2
Count is: 3
Count is: 4
```
The critical part is `count = count + 1`. Without this line, `count` would always be 0, the condition `count < 5` would always be `True`, and the loop would run forever — an **infinite loop**. This is a common programmer error, so always ensure a `while` loop's condition will eventually become `False`.

Both loops can be controlled with two special keywords: `break` and `continue`. `break` is an emergency exit — it immediately stops the loop, regardless of the condition. `continue` is a skip — it stops the current iteration of the loop and jumps straight to the next one. These are useful for handling special cases within a loop without needing complex nested `if` statements.

Combining these tools is how you build sophisticated programs. You can nest an `if` statement inside a `for` loop to filter data. You can use a `while` loop to keep asking a user for input until they give a valid answer. Control flow is the engine of your program; conditional statements and loops are the steering wheel and the accelerator.

## Real-world context

Imagine you are a junior developer working for an online shop, 'GadgetHub'. Your manager asks you to write a Python script to process the morning's orders. You have a list of orders, each being a dictionary (a collection of key-value pairs like a mini-database row). Each order has a 'total' and a 'loyalty_status'. Your job is to apply discounts, print a summary, and handle special cases.

Step-by-step, here is what an IT professional would do with control flow:

First, you would use a `for` loop to iterate over every single order in a list called `orders`. You cannot process all orders manually; a loop handles the repetition automatically.

```python
orders = [{'total': 150, 'loyalty': 'gold'}, {'total': 30, 'loyalty': 'silver'}, {'total': 200, 'loyalty': 'bronze'}]
for order in orders:
```

Inside the loop, you would need a series of `if-elif-else` statements to apply the correct discount based on `loyalty_status`. This is a classic business rule.

- If the status is 'gold', apply a 20% discount.
- If the status is 'silver', apply a 10% discount.
- If the status is 'bronze' or any other value, apply no discount.

```python
    if order['loyalty'] == 'gold':
        discount = 0.20
    elif order['loyalty'] == 'silver':
        discount = 0.10
    else:
        discount = 0.00
    final_price = order['total'] * (1 - discount)
```

Then, you need to validate the data. What if an order has a negative total? That's data corruption. You use a `while` loop or an `if` with `continue` to skip it. A `continue` inside the loop would skip the rest of the processing for that bad order and move to the next one.

```python
    if order['total'] < 0:
        print(f"Error: Skipping order with invalid total.")
        continue
```

After processing, you need to accumulate a final report. You would have a variable `total_revenue` outside the loop, and inside the loop you would add the `final_price` to it. Loops are perfect for aggregating data like this.

Finally, your manager says, "Stop the script if we have a system-wide error, like an empty order list." You would use a `while` loop to keep asking a user for a file path to a new list of orders until a valid list is loaded, or use a `break` condition to exit a loop if a critical error flag is raised.

This scenario shows how every IT professional uses control flow daily to automate data processing, validate inputs, and apply business logic. Without `for`, `if`, and `while`, you would be stuck manually editing spreadsheets — a slow, error-prone, and non-scalable nightmare. The PCAP-31-03 exam expects you to be able to write exactly these kinds of simple, practical scripts.

## Exam focus

The PCAP-31-03 exam tests 'Control Flow, Conditional Statements, and Loops' extensively. Expect 5-8 questions dedicated solely to this objective (1.2). The exam is not about writing huge programs; it is about your precision with syntax and your ability to trace the logical path of short code snippets. You must be able to predict the exact output of a given piece of code, every single time.

Here is what they specifically test and the traps they set:

**Core concepts they love:**
- The exact syntax of `if-elif-else`: You must know the colon (:) at the end of each condition line, and that indentation defines the code block. The exam will show improperly indented code and ask if it runs.
- `for` loops vs `while` loops: They will give a scenario and ask which loop is more appropriate. Know that `for` is for iterating over a known sequence, and `while` is for repeating until a condition changes.
- `range()` function: This is a favourite. Know that `range(5)` generates 0,1,2,3,4. `range(2, 8)` generates 2,3,4,5,6,7. `range(1, 10, 2)` generates 1,3,5,7,9. They will ask what the loop variable equals on the third iteration.
- `break` and `continue`: Expect a code snippet with both inside a loop. You must trace it correctly. `break` exits the entire loop; `continue` just skips to the next iteration.
- Nested loops: They will put a `for` loop inside another `for` loop. You need to know how many total times an inner loop runs.
- The `else` clause on loops: This is a sneaky PCAP feature. Yes, `for` and `while` loops can have an `else` block. The `else` block runs only if the loop finished normally (i.e., it was not terminated by a `break`). If a `break` stopped the loop, the `else` block is skipped. This is a classic exam trick.

**Common traps they set:**
- Forgetting that `range()` starts at 0 by default. Beginners often think `range(5)` gives 1 through 5. It doesn't.
- Misunderstanding the `==` operator (comparison) vs `=` (assignment). They will write `if x = 5:` which is a syntax error, but a beginner might think it works.
- Thinking that an empty sequence (like an empty list `[]`) will cause an error in a `for` loop. It doesn't — the loop simply doesn't run.
- Infinite `while` loop traps: They will show `x = 0; while x < 10: print(x)` and ask why it never ends. The answer is 'missing increment statement'.
- The order of `elif` checks: They will give conditions where two conditions could be true, but only the first one in the chain executes. You must know that `elif` stops checking once it finds a `True`.
- Short-circuit evaluation: In a compound condition like `if a > 0 and b / a > 2`, if `a` is 0, Python does not evaluate `b / a` because the whole `and` is already `False`. This avoids a division-by-zero error.

**Key definitions to memorise:**
- Boolean expression: An expression that evaluates to `True` or `False`.
- Iteration: One single execution of the loop body.
- Loop variable: The variable that takes each value in the sequence during a `for` loop.

Master these specifics. The exam is a battle of attention to detail. Knowing 'control flow' in a general sense is useless if you cannot trace why a `while` loop with a `break` and an `else` clause outputs '42' instead of '99'.

## Step by step

1. **Define the condition** — You decide what question you want to ask the program. For example, 'Is the user's age greater than 18?' This question is a boolean expression, which must result in either 'True' or 'False'. You write this condition after the 'if', 'elif', or 'while' keyword.
2. **Write the colon** — The condition must be followed by a colon (:). This colon tells Python that a new indented code block is about to start. Forgetting the colon is a common beginner syntax error that will cause your code to fail immediately.
3. **Indent the code block** — After the colon, you press 'Enter' and then indent the next line (usually by 4 spaces). All lines at this exact same indentation level are part of the block controlled by the condition. This is how Python knows which code to run or skip.
4. **Test the condition (for loops)** — When using a 'for' loop, Python first looks at the sequence you gave it (like a list or a 'range()'). It grabs the first item and assigns it to the loop variable. Then it asks: 'Is there an item to work with?' If yes, it enters the loop body. If the sequence is empty, it skips the loop entirely.
5. **Execute the loop body** — Python runs all the indented code inside the loop or conditional block once. For an 'if' statement, it runs it once if the condition is 'True'. For a 'while' loop, it runs it, then goes back to check the condition again. For a 'for' loop, it runs it for the current item, then goes back to get the next item from the sequence.
6. **Check for 'break' or 'continue'** — Inside the loop body, Python checks if it encounters a 'break' or 'continue' statement. If it sees 'break', it immediately jumps out of the entire loop, skipping the 'else' block. If it sees 'continue', it stops the current iteration and jumps back to the loop's condition test to start the next iteration.
7. **Exit the loop or conditional** — After the code block runs (and if no 'break' was hit), Python moves to the line immediately after the block (at the same indentation level as the original 'if', 'while', or 'for'). For a loop, this is where the optional 'else' block is checked. For a conditional, execution continues with the next line of the main program.

## Comparisons

### if statement vs elif statement

**if statement:**
- Runs its block only if its specific condition is the first one to be True.
- Is always the first conditional in a chain.
- Does not require any other conditional to exist after it.

**elif statement:**
- Must come after an 'if' statement.
- Can only run its block if all previous 'if' and 'elif' conditions were False.
- There can be multiple 'elif' statements in a single chain.

### for loop vs while loop

**for loop:**
- Iterates over a fixed sequence of items.
- The number of iterations is usually known beforehand.
- You cannot accidentally create an infinite loop if the sequence is finite.

**while loop:**
- Repeats as long as a condition is True.
- The number of iterations is not known beforehand.
- You can easily create an infinite loop if you forget to update the condition variable.

### break statement vs continue statement

**break statement:**
- Exits the loop completely.
- The loop's 'else' block is skipped.
- Program execution resumes at the first line after the loop.

**continue statement:**
- Skips only the current iteration of the loop.
- The loop's 'else' block will still run if no 'break' occurred.
- Program execution jumps to the top of the loop for the next iteration.

### == (equality operator) vs = (assignment operator)

**== (equality operator):**
- Compares two values and returns True or False.
- Used in conditions like 'if x == 5:'.
- Does not change the value of any variable.

**= (assignment operator):**
- Assigns a value to a variable.
- Used in statements like 'x = 5'.
- Using it in a condition ('if x = 5:') causes a syntax error.

## Diagram

_This diagram shows the general flow of a loop: the condition is checked, the block runs if true, then the condition is re-evaluated until it is false, at which point the optional else block runs and the program continues._

```mermaid
flowchart TD
    A[Start] --> B{Condition Check?}
    B -- True --> C[Execute Block]
    C --> D[Update/Next Item]
    D --> B
    B -- False --> E[Execute Else Block (if present)]
    E --> F[Continue Program]
```

## Common misconceptions

- **Misconception:** An 'if' statement can only have one 'elif' branch. **Reality:** An 'if' statement can have as many 'elif' branches as you need. There is no limit except readability. You can chain 10 'elif' blocks if necessary. (Beginners often see examples with only one or two 'elif' blocks and assume that's a hard limit. The Python syntax allows an arbitrary number of them.)
- **Misconception:** A 'while' loop will always run the code inside it at least once. **Reality:** A 'while' loop checks its condition *before* entering the loop body. If the condition is initially 'False', the code inside the loop never runs at all (zero iterations). (This is confused with 'do-while' loops which exist in other languages (like C or Java) and guarantee at least one execution. Python has no 'do-while' loop.)
- **Misconception:** Writing 'if x == True:' is the best way to check if a boolean variable is true. **Reality:** You should write 'if x:' instead. Python automatically checks if the value is 'truthy'. The '== True' is redundant and considered non-idiomatic (un-Pythonic). (Beginners come from a mathematical or formal logic background where explicit comparison feels safer. They don't trust implicit truthiness yet.)
- **Misconception:** You cannot use a list as an 'if' condition. **Reality:** You can. An empty list evaluates to 'False' in a boolean context. A non-empty list evaluates to 'True'. 'if my_list:' is a common idiom to check if a list has items. (The idea of a container being 'True' or 'False' feels strange. Beginners expect to always write 'if len(my_list) > 0:' because it is more explicit.)
- **Misconception:** The 'else' block in a 'for' loop runs when the loop finds no items to iterate over. **Reality:** The 'else' block in a 'for' loop runs when the loop finishes normally (no 'break' was hit), regardless of whether it iterated over 0 or 100 items. (The name 'else' is misleading. It does not mean 'if the loop didn't run'. It means 'if the loop didn't break'. This is almost never self-intuitive.)

## Key takeaways

- An 'if' statement executes its code block only when its condition evaluates to 'True'.
- Use 'elif' to check multiple mutually exclusive conditions in a single chain.
- A 'for' loop iterates over each item in a sequence, such as a list, tuple, or string.
- A 'while' loop continues to execute as long as its condition remains 'True'.
- The 'break' keyword immediately exits the innermost loop it is placed in.
- The 'continue' keyword skips the rest of the current loop iteration and moves to the next one.
- A 'for' or 'while' loop's 'else' block runs only if the loop was not terminated by a 'break' statement.
- Indentation in Python defines a block of code; incorrect indentation causes an 'IndentationError'.

## FAQ

**What is the difference between 'if' and 'elif'? Why not just use multiple 'if' statements?**

Use 'elif' when you have mutually exclusive conditions. If you use multiple 'if' statements, every condition is checked independently, and multiple blocks can run. With 'elif', only the first true block runs, and the rest of the chain is skipped.

**My 'while' loop runs forever. What's wrong?**

Your 'while' loop's condition is never becoming 'False'. Most likely, you forgot to update the variable that is being checked in the condition. For example, if you loop 'while x < 10' but never add anything to 'x', it will loop forever. Add an increment like 'x = x + 1' inside the loop.

**Can I put a 'for' loop inside another 'for' loop?**

Yes, that is called a nested loop. The inner loop runs completely for every single iteration of the outer loop. For example, if the outer loop runs 3 times and the inner loop runs 4 times, the inner loop's code runs 12 times in total.

**What does 'range(10)' give me? Does it include 10?**

'range(10)' generates a sequence of numbers starting at 0 and stopping before 10. It produces 0,1,2,3,4,5,6,7,8,9. It does NOT include 10. This is a common off-by-one error.

**What is a 'truthy' value in Python?**

A 'truthy' value is any value that Python considers 'True' when used in a boolean context like an 'if' condition. Non-empty strings, non-zero numbers, and non-empty lists are truthy. Empty strings, zero, and 'None' are 'falsy'.

**When does the 'else' block of a 'for' loop run?**

The 'else' block of a 'for' (or 'while') loop runs when the loop finishes normally, meaning it was not terminated by a 'break' statement. It runs even if the loop iterated over zero items.

## Check your understanding

1. **What will the following code print? x = 10; if x > 5: print('A'); elif x > 8: print('B'); else: print('C');**

   Answer: It will print 'A'. The first condition ('x > 5') is True, so it runs that block and skips the 'elif' and 'else' entirely.

2. **How many times will the word 'Hello' be printed? for i in range(3): for j in range(2): print('Hello')**

   Answer: It will print 'Hello' 6 times. The outer loop runs 3 times, and the inner loop runs 2 times for each outer iteration (3 * 2 = 6).

3. **What is the output? count = 0; while count < 3: print(count); count = count + 1; else: print('Done');**

   Answer: The output is 0, then 1, then 2, then 'Done'. The loop finishes normally (no break), so the 'else' block executes.

4. **What does the 'continue' statement do inside a loop?**

   Answer: It stops the current iteration of the loop and jumps immediately to the next iteration, skipping any code after the 'continue' in the loop body.

5. **Is this code valid? if x = 10: print('Ten')**

   Answer: No, it is not valid. Using a single equals sign (=) inside an 'if' condition is an assignment, not a comparison. It will cause a SyntaxError.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/python-pcap/control-flow-and-loops
