# Conditional Statements

Course: [Python](https://www.devtutorials.ai/learn/python) · Section: Control Flow
Source: https://www.devtutorials.ai/learn/python/control-flow/conditional-statements

> How to run code only when a test is true: if, else, elif chains and why their order matters, nesting, and the one-line conditional expression.

Think about getting ready for school in the morning.

You look outside. If it is raining, you take an umbrella. If it is not, you leave it at home.

You made a decision. You checked something, and what you did next depended on the answer.

Programs make decisions the same way, and the word they use is `if`.

```python runnable title="A program that decides"
marks = 78

if marks >= 35:
    print("Passed")
```

The program checked whether the marks were 35 or more. They were, so it printed `Passed`.

Change `78` to `20` and run it again. Nothing is printed at all, because the test was false and the indented line was skipped.

## What You Will Learn

In this lesson, you will learn:

- How to run some code only when a test is true
- How to give the program something else to do when the test is false
- How to check several conditions in order, and why the order matters
- How to put one decision inside another, and when not to
- How to choose between two values in a single line

A conditional statement runs a block of code only when a test is true.

## Introduction to Conditional Statements

### What Is a Conditional Statement?

A **conditional statement** is a block of code that runs only when a test is true.

The test is called the **condition**. It is anything that produces `True` or `False`.

For example, `marks >= 35` is a condition. Python checks it and gets either `True` or `False`, and the conditional statement uses that answer to decide what to do next.

### Why Conditional Statements Are Used

Without conditions, a program does exactly the same thing every time it runs. It cannot react to anything.

```python runnable title="The same thing, every time"
marks = 20

print("Result for the term")
print("Marks:", marks)
print("Passed")
```

That program prints `Passed` for a mark of 20, which is wrong. It has no way to tell the difference.

With a condition, the program responds to what it is given:

```python runnable title="A program that reacts"
PASS_MARK = 35
marks = 20

print("Result for the term")
print("Marks:", marks)

if marks >= PASS_MARK:
    print("Passed")

if marks < PASS_MARK:
    print("Failed")
```

Same program, honest answer. The condition is what makes a program useful rather than a fixed list of instructions. Every useful program — a game, a login check, a marks sheet — has to react to what happens, and this is the tool that lets it.

## if Statement

### What Is an if Statement?

An `if` statement runs a block of code when its condition is true, and skips it when the condition is false.

### Syntax of if Statement

```text
if condition:
    code that runs when the condition is true
```

Three parts matter, and leaving any of them out stops the program:

- the word `if`
- the condition
- a colon `:` at the end of the line

The lines under it must be indented by four spaces. The indentation is what tells Python which lines belong to the `if`.

```python runnable title="The shape of an if statement"
attendance = 92

if attendance >= 75:
    print("Attendance is fine")
    print("No letter needed")

print("Report finished")
```

Two lines are indented, so both belong to the `if`. The last line is not indented, so it runs whatever the answer was.

### Executing Conditional Code

The condition can be any expression that gives `True` or `False`.

```python runnable title="Four different conditions"
marks = 78
remark = "Good work"

if marks > 75:
    print("Above 75")

if marks != 100:
    print("Not full marks")

if "work" in remark:
    print("The remark mentions work")

if marks:
    print("Marks is not zero")
```

The first three conditions are comparisons you have met before. The last one is worth a second look. `marks` is not a comparison, but Python can still read any value as true or false. `78` counts as true, so the line runs. `0` would count as false.

### Simple Examples

```python runnable stdin="92" title="A decision made from what the user types"
attendance = int(input("Attendance percent: "))

if attendance < 75:
    print("Attendance is below the required 75 percent")

print("Checked")
```

The Input box holds 92, so nothing is printed about attendance. Change it to 60 and run again. The warning appears.

Forgetting the colon is the most common slip here:

```python runnable expect-error title="A missing colon"
marks = 78

if marks >= 35
    print("Passed")
```

`SyntaxError: expected ':'` is Python saying the line looked like an `if` but never finished. The editor marks this one as you type.

## if else Statement

### What Is an if else Statement?

`else` gives the program something to do when the condition is false.

```text
if condition:
    code for when the condition is true
else:
    code for when it is false
```

`else` has no condition of its own. It catches everything the `if` did not.

```python runnable title="Two paths, one of them always runs"
PASS_MARK = 35
marks = 20

if marks >= PASS_MARK:
    print("Passed")
else:
    print("Failed")
```

### Alternative Execution Paths

Exactly one of the two blocks runs. Never both, never neither.

```python runnable title="Only one block runs"
attendance = 60

if attendance >= 75:
    print("Attendance is fine")
    print("No action needed")
else:
    print("Attendance is low")
    print("A letter will be sent home")

print("Done")
```

Compare this with the two separate `if` statements from earlier. Two `if` statements test twice; an `if else` tests once and chooses. If the two cases are opposites, `else` says so more clearly and cannot get out of step.

### Using if else Effectively

Write the condition for the case you care about most, and let `else` handle the rest.

```python runnable title="The important case first"
marks = 78

if marks >= 75:
    print("Distinction")
else:
    print("No distinction")
```

Avoid testing the same thing twice in opposite directions:

```python runnable title="Testing the same thing twice"
marks = 78

if marks >= 35:
    print("Passed")

if marks < 35:
    print("Failed")
```

This works, but the two conditions have to stay opposite for ever. Change 35 to 40 in one line and not the other, and a mark of 37 prints nothing at all. `else` cannot drift that way, because there is only one condition to keep correct.

If the second test is the exact opposite of the first, use `else`. One condition is one thing to keep correct instead of two.

## if elif else Statement

### Multiple Conditions

`elif` is short for "else if". It adds another condition to test when the one above was false.

```text
if first condition:
    ...
elif second condition:
    ...
else:
    ...
```

```python runnable title="Turning a mark into a grade"
marks = 78

if marks >= 80:
    print("Grade A")
elif marks >= 60:
    print("Grade B")
elif marks >= 35:
    print("Grade C")
else:
    print("Fail")
```

A mark of 78 is not 80 or more, so the first test failed. It is 60 or more, so the second succeeded and printed `Grade B`.

You can have as many `elif` branches as you need. The `else` at the end is optional.

### Decision Chains

The whole chain is one statement, and **only one branch ever runs**.

```python runnable title="Only one branch runs, even when several fit"
marks = 90

if marks >= 80:
    print("Grade A")
elif marks >= 60:
    print("Grade B")
elif marks >= 35:
    print("Grade C")
```

A mark of 90 is 80 or more, 60 or more, and 35 or more. All three conditions are true. Only `Grade A` printed, because Python stops at the first branch that succeeds.

### Condition Evaluation Order

Python reads the branches from the top down and stops at the first true one. That makes the order part of the meaning.

Here is the same chain with the conditions in the wrong order:

```python runnable title="The wrong order gives the wrong grade"
marks = 90

if marks >= 35:
    print("Grade C")
elif marks >= 60:
    print("Grade B")
elif marks >= 80:
    print("Grade A")
```

A mark of 90 now prints `Grade C`. Nothing is broken: 90 really is 35 or more, so the first branch matched and the rest were never read.

The two later branches can never run at all. Every mark that would reach them was already caught by the first.

In an `if elif else` chain, put the narrowest condition first and the widest last. A wide condition at the top swallows every branch below it, and the program still runs without an error.

## Nested Conditions

### Nested if Statements

An `if` can go inside another `if`. This is called **nesting**.

The inner test is only reached when the outer one is true.

```python runnable title="A test inside a test"
marks = 90
attendance = 92

if marks >= 35:
    print("Passed")
    if marks >= 80:
        print("With distinction")
```

`With distinction` is indented twice, so it runs only when both tests are true.

### Nested if else Statements

```python runnable title="A choice inside a choice"
marks = 90
attendance = 60

if marks >= 35:
    if attendance >= 75:
        print("Promoted")
    else:
        print("Passed the exam, but attendance is too low")
else:
    print("Failed")
```

The student passed the exam, so Python went into the first block. Inside it, attendance was below 75, so the `else` ran.

### Best Practices

Nesting works, but every level moves the code further right and makes it harder to follow. Two levels are fine. Four are a sign something should change.

Most nesting can be replaced with `and`, putting both tests in one condition instead of one inside the other:

```python runnable title="The same rule without nesting"
marks = 90
attendance = 60

if marks >= 35 and attendance >= 75:
    print("Promoted")
elif marks >= 35:
    print("Passed the exam, but attendance is too low")
else:
    print("Failed")
```

Same three outcomes, one level of indentation, and the rule reads as a sentence.

Another way to reduce nesting is to deal with the simple case first and get it out of the way:

```python runnable title="Handling the simple case first"
marks = 20

if marks < 35:
    print("Failed")
else:
    if marks >= 80:
        print("Distinction")
    else:
        print("Passed")
```

Reach for `and` before you reach for a second level of indentation. Keep nesting for the cases where the inner question only makes sense once the outer one is answered.

## Conditional Expressions

### One-Line Conditions

A **conditional expression** chooses between two values in a single line.

```text
value_if_true if condition else value_if_false
```

```python runnable title="A choice written on one line"
PASS_MARK = 35
marks = 78

print("Pass" if marks >= PASS_MARK else "Fail")
```

Read it as a sentence: *"Pass", if the marks reach the pass mark, otherwise "Fail".*

### Conditional Assignment

The usual use is to store the chosen value in a variable.

```python runnable title="Storing the chosen value"
PASS_MARK = 35
marks = 20

result = "Pass" if marks >= PASS_MARK else "Fail"

print("Result:", result)
```

Four lines of `if else` become one. Both forms are correct, and the right choice depends on how much happens in each branch.

```python runnable title="The same thing as a full if else"
PASS_MARK = 35
marks = 20

if marks >= PASS_MARK:
    result = "Pass"
else:
    result = "Fail"

print("Result:", result)
```

A conditional expression must always have its `else`. Leaving it out is an error, because the expression has to produce a value either way:

```python runnable expect-error title="A conditional expression with no else"
marks = 78

result = "Pass" if marks >= 35

print(result)
```

They can be chained, but a chain quickly becomes hard to read:

```python runnable title="A chain that is already too long"
marks = 78

grade = "A" if marks >= 80 else "B" if marks >= 60 else "C" if marks >= 35 else "F"

print(grade)
```

That line is correct and gives `B`. An `if elif else` chain says the same thing in a way anyone can read at a glance. Use the one-line form for a simple either-or, and the full statement for anything longer.

## Common mistakes

Each row is one mistake. The middle column is what you will actually see on screen.

<div className="tscroll">

| Mistake | What you see | Why it happens | Fix |
|---|---|---|---|
| Forgetting the colon | `SyntaxError: expected ':'` | An `if` line must end in `:` | `if marks >= 35:` |
| Forgetting to indent the block | `IndentationError: expected an indented block` | A `:` promises a block, so the block must be there | Indent the next line by four spaces |
| Using `=` instead of `==` | `SyntaxError: invalid syntax` | One `=` stores a value; a test needs two | `if marks == 78:` |
| Widest condition first in a chain | A wrong grade, with no error at all | Python stops at the first true branch | Put the narrowest condition first |
| Using several `if`s where `else` belongs | Two messages printed, or none | Separate `if`s are tested separately and can drift apart | Use `if` / `else` for opposite cases |
| A condition that can never be true | A branch that silently never runs | An earlier branch already covers every value | Read the chain from the top and check each branch can be reached |
| Leaving out `else` in a one-line choice | `SyntaxError: invalid syntax` | A conditional expression must produce a value either way | Add the `else` part |
| Indenting a line that should run always | A line that only runs sometimes | Indentation decides what belongs to the block | Move it back to the left margin |
| Comparing text to a number | `TypeError: '>=' not supported` | `input()` hands back text, which cannot be compared to a number | Wrap it in `int()` first |

</div>

## What to Remember

- **A conditional statement runs a block of code only when a test is true.**
- An `if` line ends in a colon, and the block under it is indented by four spaces.
- `else` catches everything the `if` did not, and needs no condition of its own.
- `elif` adds another condition to try when the ones above were false.
- **Only one branch of a chain ever runs**, and Python stops at the first true one.
- Order is part of the meaning: the narrowest condition goes first, the widest last.
- A wide condition at the top makes the branches below it unreachable, with no error.
- Nesting puts one decision inside another. Prefer `and` unless the inner question depends on the outer one.
- `value_if_true if condition else value_if_false` chooses between two values in one line, and its `else` is required.

Next: **Pattern Matching**
