Addaly is in open beta. Things will change, and AI answers can be wrong — check anything that matters.

Python, From Zero, For AI

From your first line of code to your first API call.

Lesson 9 of 897 min

Making a decision: if, elif, else

The shape

python
marks = 72

if marks >= 75:
    grade = "distinction"
elif marks >= 60:
    grade = "first"
elif marks >= 40:
    grade = "pass"
else:
    grade = "fail"

print(grade)

Four things are load-bearing here.

The colon ends the condition line. Forget it and you get SyntaxError: expected ':'.

The indentation decides what belongs to the branch. Four spaces, consistently. Python does not care whether it is four or two, but it cares that you never change your mind inside one file, and mixing tabs with spaces produces TabError at a line that looks identical to the one above it. Set your editor to insert spaces when you press Tab and forget about it.

elif means "otherwise, if" and only one branch ever runs. The moment a condition is true, Python executes that block and skips the rest of the chain.

else has no condition. It catches everything left.

The bug that a chain of ifs creates

Write the same logic with four separate if statements instead:

python
if marks >= 75:
    grade = "distinction"
if marks >= 60:
    grade = "first"
if marks >= 40:
    grade = "pass"

Now every mark of 80 gets tested three times, all three are true, and grade ends up as "pass" because the last assignment wins. The program produces a wrong answer without any error. This is one of the most common logic bugs in beginner code and it never announces itself.

If the branches are alternatives, use elif. Use separate ifs only when the conditions are genuinely independent and more than one is allowed to fire.

Order matters inside a chain

Reverse the chain and it breaks in a different way:

python
if marks >= 40:
    grade = "pass"
elif marks >= 75:
    grade = "distinction"     # unreachable

Every mark of 75 already satisfied the first test, so the second is never reached. distinction becomes dead code. Nothing warns you.

The rule for numeric bands: order from the most restrictive to the least, or from the largest threshold down. Then check the boundaries by hand — 39, 40, 59, 60, 74, 75. Boundary errors are where nearly all of these bugs live, and testing exactly the boundary values takes a minute.

Nesting, and how to avoid it

Conditions inside conditions get unreadable fast:

python
if user is not None:
    if user.is_active:
        if user.has_credit:
            place_order()

Turn it inside out with guard clauses — deal with the reasons to stop first, then let the main path sit unindented:

python
if user is None:
    return "no such user"
if not user.is_active:
    return "account suspended"
if not user.has_credit:
    return "insufficient credit"
place_order()

Same logic, one level of indentation, and each rejection now has its own message instead of a silent fall-through. That last part is the real gain: the nested version cannot easily tell you which condition failed.

Two syntax notes

= assigns, == compares. Writing if x = 5: is a SyntaxError in Python, which is a small mercy — in C it compiles and quietly assigns.

An if cannot be empty. If you want a branch that does nothing yet, write pass:

python
if debug_mode:
    pass    # TODO

The conditional expression

When you are choosing between two values rather than two actions, there is a one-line form:

python
status = "adult" if age >= 18 else "minor"

Read it as: the value is "adult", if age >= 18, otherwise "minor". Fine for a simple choice, unreadable once nested. If you find yourself writing two of them in one line, use a proper if block.

match, since Python 3.10

For comparing one value against many fixed possibilities there is now a match statement:

python
match command:
    case "start":
        run()
    case "stop" | "halt":
        halt()
    case _:
        print("unknown command")

It is more than a switch — it can destructure lists and dictionaries — but for plain values it reads better than a long elif chain. Two honest cautions: it needs 3.10 or newer, and a bare name in a case pattern binds rather than compares, so case ready: matches anything and assigns to ready, which is a genuinely nasty surprise. Compare against literals or dotted names, and the trap never appears.

Try this now

Write the grade chain, then run it with marks of 39, 40, 74, 75 and 100. Then deliberately reverse two branches and watch a correct-looking program give a wrong grade with no error message. That failure mode is worth seeing once on purpose.

The one thing to keep

In an if/elif chain only the first true branch runs, so replacing elif with separate ifs lets a later assignment overwrite an earlier correct one with no error.

Before you move on

A shipping calculator uses `if weight > 0: rate = 50` then `if weight > 5: rate = 90` then `if weight > 20: rate = 200`, all as separate `if` statements, and a 3 kg parcel is charged 50 while a 25 kg parcel is charged 200. The developer concludes the logic is fine. What is the risk?

Pick the one you would defend. Nobody sees your answer.

No ads. No data sale. No public scores on people. Ever.

© 2026 Addaly