SchoolWhool
Quizzes and saved progress, freeSign in freeSign in

Python 2.1Free video21 minLesson 1 of 4 in Module 2

if, elif and else

Make the program choose.

Free sample. Everything in this module opens with a free account.

Watch or read the lesson: if, elif and else

01A shipping rule: one program chooses between two outcomes

In the operators lesson, you learned how to compare values in Python. You used operators like >, < and ==, and every one of those comparisons gave you either True or False.

That raises a question: what do you actually do with those results?

Imagine you are building a small online store, and the store has a simple shipping policy:

  • If someone spends $50 or more, they get free shipping.
  • Otherwise, shipping costs $4.99.

So if someone places an order worth $62.40, shipping should be free. But if their order is only $38.75, they should pay $4.99 for shipping.

You could calculate the shipping charge by hand for every order, but that would not be very useful. What you want is for Python to make that decision automatically: one program that looks at the order total and picks the right outcome on its own.

That is what this lesson is about. It starts with if, then adds else and elif, and then looks at a few other ways Python lets you control which code runs.

02The if statement: the condition, the colon and the indented block

Start with the shipping example. Suppose the order total is $62.40, so the first line is total = 62.40.

Now you want to check whether the total is at least 50. For that, you use an if statement. The next line is if total >= 50:.

The condition and the colon

Look at that line piece by piece.

  • The word if tells Python that you are about to make a decision.
  • The expression total >= 50 is called the conditionKey termAn expression whose truth value an if or a while tests, such as total >= 50 or name.. Python evaluates the condition to decide whether the code underneath it should run.
  • The colon at the end is important. It tells Python that a block of code follows.

The indented block

On the next line, write shipping = 0.0. But there is something different about this line: it is indented, moved slightly to the right.

That indentation is not just for appearance. It tells Python that this statement belongs to the if. The indented lines under an if are called its blockKey termThe indented lines that belong to an if, else, while, for or case. The first line back at the outer level ends it., and whenever the condition is True, Python runs the block.

Running it

Add a print call after the block, back at the left edge, so you can see the shipping charge, and run the cell:

total = 62.40
if total >= 50:
    shipping = 0.0
print(shipping)
0.0

The total is 62.40, and the condition checks whether it is greater than or equal to 50. That is True, so Python enters the block and assigns 0.0 to shipping. Once the block is finished, Python continues with the next statement outside it, the print, which displays 0.0. That is exactly what the shipping policy says.

So the flow is simple:

  1. Python evaluates the condition.
  2. If it is True, Python runs the block.
  3. Then it continues with the rest of the program.

03Indentation, IndentationError and the missing colon

Before going further, it is worth spending a little time on indentation, because you will see it everywhere in Python.

In many programming languages, blocks of code are surrounded by curly braces. Python does things differently: it uses indentation to define blocks. When several statements belong to the same if, they all need to be indented to the same level. And when a line moves back to the previous indentation level, Python knows that the block has ended.

How many spaces should you use? Python's style guide, PEP 8, recommends four spaces per indentation level. Colab usually indents the next line for you automatically after a colon, but you should still pay attention to indentation, because it changes how your code runs.

Expected an indented block

Here is what happens when you get it wrong. Remove the indentation from the line that assigns 0.0 to shipping, and run the cell:

total = 62.40
if total >= 50:
shipping = 0.0
IndentationError: expected an indented block after 'if' statement on line 2

Python raises an IndentationError. The message says it expected an indented block after the if statement on line 2.

Notice that Python has not even reached the point of checking the condition. The code is not structured correctly, so Python cannot run any of it. Not even the first line, total = 62.40, runs.

Two more indentation errors

There are a few other indentation errors you might meet. If you indent a line when Python is not expecting a new block, you get an unexpected indent:

total = 62.40
    shipping = 0.0
IndentationError: unexpected indent

And if you move back to an indentation level that does not match any earlier level, Python reports that the unindent does not match any outer indentation level. Here the print is indented by two spaces, which is neither the four spaces of the block nor the zero spaces of the if:

if total >= 50:
    shipping = 0.0
  print(shipping)
IndentationError: unindent does not match any outer indentation level

These messages can look confusing at first, but the fix usually comes down to one question: which block is this statement supposed to belong to? Once you know that, align it with the other statements in that block.

The missing colon

There are two other small mistakes worth knowing about. The first is forgetting the colon after the condition:

total = 62.40
if total >= 50
    shipping = 0.0
SyntaxError: expected ':'

Python raises a SyntaxError, because the colon is part of the syntax of an if statement. Without it, the line is not valid Python.

A single equals sign

The second mistake is confusing assignment with comparison. Suppose you write if total = 50::

total = 62.40
if total = 50:
    shipping = 0.0
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

That does not work. Remember, a single equals sign is used for assignment, not for comparison. If you want to check equality, you need two equals signs, ==. And in the shipping example you actually want "greater than or equal to", so the condition uses >=.

04else and elif: two branches, and more than two

Fix the code and get back to the shipping calculation. So far, you have tested an order worth $62.40, and everything works. But what happens if the order total is smaller? Try $38.75.

Before you do, restart the Colab session (Runtime, then Restart session) so you are working with a clean state. You do not want the shipping value from the earlier run to affect what happens next.

Now set the total to 38.75 and run the same if statement:

total = 38.75
if total >= 50:
    shipping = 0.0

This cell shows no output. This time, the condition is False, because 38.75 is not greater than or equal to 50, so Python skips the indented block.

Predict first

But here is the interesting part. The only place shipping was given a value is inside that block, and since the block did not run, shipping has not been defined. So what do you think happens when you print it in the next cell? Think it through before reading on.

I have a guess. Show meHide the answer
print(shipping)
NameError: name 'shipping' is not defined

Python raises a NameError: the name shipping is not defined.

This connects directly to something from the lesson where you ran your first Python code: just because a statement is visible in a cell does not mean Python has executed it. The line shipping = 0.0 is right there on the screen, but Python never ran it.

else

How do you fix that? You need to tell Python what to do when the condition is False, and that is where else comes in.

Add an else block underneath the if. The else lines up with the if, and inside it you assign 4.99 to shipping. Now the program has two possible paths:

  • If the order total is at least 50, shipping is 0.0.
  • Otherwise, shipping is 4.99.

Notice that else does not have a condition. It handles every case where the if condition was False. These two paths are called branches, and when you use if and else together, exactly one of the branches runs.

Test it with the total of 38.75. The cell also prints the order total plus shipping, to two decimal places:

if total >= 50:
    shipping = 0.0
else:
    shipping = 4.99
print(shipping)
print(f"{total + shipping:.2f}")
4.99
43.74

With a total of 38.75, Python skips the first block and runs the else block, so shipping becomes 4.99, and the order total plus shipping is $43.74.

Now change the order total back to 62.40 and run it again:

total = 62.40
if total >= 50:
    shipping = 0.0
else:
    shipping = 4.99
print(shipping)
print(f"{total + shipping:.2f}")
0.0
62.40

This time the if condition is True, so shipping becomes 0.0 and Python skips the else block. You have written one program that handles both situations.

elif

What if there are more than two possibilities? Here is another example. Imagine you are building a ticket booking system for a cinema, and the cinema has three ticket prices:

  • Children under 12 pay $8.
  • People aged 65 or older pay $9.
  • Everyone else pays $12.50.

Now there are three possible outcomes. You could write several separate conditions, but Python gives you a clearer way: if, elif and else.

Start with the child discount: an if statement that checks whether age is less than 12, and if that is True, assigns the child price.

Then comes elif, which is short for "else if". It lets you check another condition, but only if the conditions before it were False. Here, it checks whether age is greater than or equal to 65, and if so assigns the senior price.

Finally, else covers everyone who does not qualify for either discount, with the standard price of $12.50:

age = 9
if age < 12:
    price = 8.00
elif age >= 65:
    price = 9.00
else:
    price = 12.50
print(price)
8.0

How Python works through the chain

Python evaluates an if/elif/else chain from the top:

  1. If the first condition is True, Python runs that block and skips the remaining branches.
  2. If the first condition is False, it moves to the next condition.
  3. It keeps going until it finds a condition that is True.
  4. If none of the conditions is True, it runs the else block.

That is what happened with age 9 above. Is 9 less than 12? Yes. So Python assigns the child price, 8.0, and does not need to check the senior condition at all.

Now try age 30:

age = 30
if age < 12:
    price = 8.00
elif age >= 65:
    price = 9.00
else:
    price = 12.50
print(price)
12.5

The first condition is False, and the second condition is False too, so Python reaches the else block and assigns the standard price.

And finally age 70:

age = 70
if age < 12:
    price = 8.00
elif age >= 65:
    price = 9.00
else:
    price = 12.50
print(price)
9.0

The child condition is False, but the senior condition is True, so the ticket price is $9.

The boundaries

Now check the boundaries. What happens at exactly age 12? The child condition is age < 12:

12 < 12
False

12 is not less than 12, so the child discount does not apply, and a 12-year-old pays the standard price. What about exactly age 65?

65 >= 65
True

That does qualify for the senior discount, because the condition is "greater than or equal to 65".

Boundary cases like these matter, especially when you write code for discounts, eligibility rules or age restrictions. Using < instead of <= changes who qualifies.

05The conditional expression: if and else in one line

Sometimes a decision is much simpler: you just want to choose between two values. Remember the shipping rule? If the total is at least 50, shipping is 0.0. Otherwise, it is 4.99.

You could write that with a full if and else block, but Python also gives you a shorter option, called a conditional expressionKey terma if condition else b, an expression that gives one of two values: 0.0 if total >= 50 else 4.99.. Set up a total in one cell:

total = 38.75

Then write the conditional expression in the next:

shipping = 0.0 if total >= 50 else 4.99
shipping
4.99

The order might look a little unusual at first:

  1. Start with the value you want when the condition is True: 0.0.
  2. Then write if, followed by the condition: total >= 50.
  3. After else, write the value you want when the condition is False: 4.99.

So Python checks whether the total is at least 50. If it is, the expression produces 0.0. Otherwise, it produces 4.99. That result is then assigned to shipping. With a total of 38.75, it is 4.99.

When to use it

A conditional expression is a convenient way to write a simple choice between two values. But if your branches contain several statements, use a regular if and else. That is usually easier to read as well.

06Truthiness: truthy and falsy values, and the or operand bug

So far, every condition in this lesson has been a comparison, something like age < 12 or total >= 50. But an if statement does not actually require a comparison. It can test a value directly.

In the data types lesson, you saw Boolean conversion: bool() treats certain values as True and others as False. An if statement uses exactly the same idea, and this behavior is called truthinessKey termWhether a value counts as True or False when it is used as a condition. Falsy built-in values include False, None, zero of any numeric type, and empty strings or collections. Nonzero numbers and nonempty strings are truthy.. A value that is treated as True in a condition is called truthy, and a value that is treated as False is called falsy.

For the basic types you have met so far, False, None, zero and an empty string are falsy:

bool(False), bool(None), bool(0), bool(0.0), bool("")
(False, False, False, False, False)

Nonzero numbers and nonempty strings are truthy.

Which values would make an if block run?

Predict first

Here are five values: the integer 0, the string "0", a string containing a single space " ", None, and the string "False". Which of them would make an if block run? Think it through before reading on.

I have a guess. Show meHide the answer

The integer zero is falsy, and None is falsy too:

bool(0), bool(None)
(False, False)

But the other three values are all truthy, yes, even the string "False":

bool("0"), bool(" "), bool("False")
(True, True, True)

Python is not looking at what the string means. It only checks whether the string is empty, and all three of these strings contain at least one character, so they are truthy.

if name:

Where is this useful? Imagine you ask a user to enter their name, storing the result with input("Name: "), and then you want to display a greeting. If they enter a name, you greet them by that name. But if they just press Enter without typing anything, input() returns an empty string, and you want to say Hello, Guest.

You can do this with a simple if name: condition. Here the name is set directly in the cell, so you can see both cases. First with a name:

name = "Asha"
if name:
    print(f"Hello, {name}")
else:
    print("Hello, Guest")
Hello, Asha

The string is nonempty, so the condition is truthy and Python displays the greeting with the name. Now with an empty string, which is what you get when someone presses Enter without typing:

name = ""
if name:
    print(f"Hello, {name}")
else:
    print("Hello, Guest")
Hello, Guest

The empty string is falsy, so Python runs the else block.

One thing to keep in mind: this only checks whether the string is empty. It does not check whether the name is a valid name. If the user enters only spaces, that is still a nonempty string, so the condition is truthy.

The weekend check

Here is a mistake that catches a lot of beginners, and the interesting thing is that the code looks perfectly reasonable. Suppose you have a variable called day, and its value is "Monday". You want to check whether today is a weekend, so you write day == "Saturday" or "Sunday":

day = "Monday"
if day == "Saturday" or "Sunday":
    print("Weekend")
else:
    print("Weekday")
Weekend

At first glance, the condition looks like it checks whether the day is Saturday or Sunday. But it is Monday, and Python printed Weekend. Here is what Python actually does.

The left side of or is a comparison, day == "Saturday". Since day is "Monday", that comparison is False.

But look at the right side. It is just the string "Sunday". There is no comparison there at all.

Remember how or works from the operators lesson: when the left operand is falsy, Python evaluates and returns the right operand. So this expression produces the string "Sunday":

day = "Monday"
day == "Saturday" or "Sunday"
'Sunday'

Is that string truthy? Yes, because it is not empty. So when you use this expression in an if statement, Python runs the weekend branch, even though today is Monday. That is clearly not what you wanted.

The fix

To fix it, write both comparisons explicitly: day == "Saturday" or day == "Sunday".

day = "Monday"
if day == "Saturday" or day == "Sunday":
    print("Weekend")
else:
    print("Weekday")
Weekday

Now Python checks whether day is "Saturday", and if that comparison is False, it checks whether day is "Sunday". For Monday, both comparisons are False, so the weekend condition is False. And for Sunday:

day = "Sunday"
if day == "Saturday" or day == "Sunday":
    print("Weekend")
else:
    print("Weekday")
Weekend

the second comparison is True. That is the behavior you wanted.

07Separate if statements and nested if statements

Here is another question: would two separate if statements behave the same way as an if and elif chain?

Suppose you are assigning grades based on a student's score, and each student should get exactly one grade:

  • A score of 90 or more gets an A.
  • A score from 80 up to, but not including, 90 gets a B.

Say the student scored 95. You write one if statement that checks whether the score is at least 90, and a second, separate if statement that checks whether it is at least 80:

score = 95
if score >= 90:
    print("A")
if score >= 80:
    print("B")
Predict first

Will those two checks give you the single grade you want? Think it through before reading on.

I have a guess. Show meHide the answer
A
B

Python prints both A and B. These are two independent if statements, so Python evaluates both conditions separately. Since 95 is greater than both 90 and 80, both blocks run.

Changing the second if to elif

Now change the second if to elif and run the code again:

score = 95
if score >= 90:
    print("A")
elif score >= 80:
    print("B")
A

This time, you only get A. Both conditions are now part of one chain, and once the first condition is True, Python skips the remaining branches in that chain.

Nested if statements

Sometimes one decision depends on another, and that is where nested if statements come in.

Take a simple login check with a username and a PIN. First you check whether the username is "asha", and only if the username matches do you check the PIN. So you put a second if statement inside the first one's block. An if statement inside another block is called a nested if.

username = "asha"
pin = "4821"
if username == "asha":
    if pin == "4821":
        print("Welcome")
    else:
        print("Wrong PIN")
else:
    print("Unknown user")
Welcome

Because the inner if belongs to the outer block, it is indented one level further, and its own block is indented one level further again. The same indentation rules still apply: the inner else lines up with the inner if, and the outer else lines up with the outer if. That alignment is how Python knows which if each else belongs to.

08match and case: literal values and the wildcard pattern

There is one more way Python lets you choose between different cases: match and case. This feature is called structural pattern matching, and it was introduced in Python 3.10.

Say you are working with HTTP status codes. These are numbers that a website or server returns to indicate what happened with a request. For example:

  • 200 means OK.
  • 404 means Not Found.
  • 500 or 503 indicates a server error.

Suppose you want to display a message based on the status code. You could write an if/elif/else chain, but this time, use match.

Writing the cases

Start with match code:. Then, underneath it, write a series of case blocks. Each case contains a pattern that Python tries to match against the value of code.

  • case 200: matches the value 200, and inside that block you assign the message "OK".
  • case 404: assigns "Not Found".
  • For server errors, case 500 | 503: matches either 500 or 503.

Inside a pattern, the vertical bar | combines alternative patterns: the case matches if any one of them matches. This is not the same thing as the logical or operator from earlier in the lesson. It only has this meaning inside a case pattern.

The wildcard pattern

Finally, add case _:. The underscore is called the wildcard pattern. It matches anything that was not handled by an earlier case, so you can use it as the default case, the same way else works at the end of an if chain.

Test it with the code 503:

code = 503
match code:
    case 200:
        text = "OK"
    case 404:
        text = "Not Found"
    case 500 | 503:
        text = "Server Error"
    case _:
        text = "Unknown"
print(text)
Server Error

Python matches the server error case, so you get Server Error. Now try 418:

code = 418
match code:
    case 200:
        text = "OK"
    case 404:
        text = "Not Found"
    case 500 | 503:
        text = "Server Error"
    case _:
        text = "Unknown"
print(text)
Unknown

None of the specific cases match 418, so Python reaches the wildcard case and you get Unknown.

match and case can do much more than compare fixed values, but this is a good place to start. When you are choosing between a fixed set of values, match can be quite readable.

09Recap and challenge: if, elif, else, truthiness and match

This lesson started with a simple shipping problem and used if to let Python make a decision based on a condition. Then it added else to handle the alternative case, and elif to choose between several possibilities.

Indentation is part of Python's syntax: it determines which statements belong to which block. And the order of conditions matters, because Python stops checking an if/elif chain as soon as it finds a branch whose condition is True.

Truthiness explained why a nonempty string like "False" is still treated as True in a condition, and why day == "Saturday" or "Sunday" is always truthy. Along the way you also met conditional expressions, nested if statements, and structural pattern matching with match and case.

Your challenge

Remember the cinema ticket example:

  • Children under 12 pay $8.
  • People aged 65 and over pay $9.
  • Everyone else pays $12.50.

The cinema has just introduced another discount: students can now buy a ticket for $10.

  1. Extend the ticket pricing program to include the student discount.
  2. Make sure every customer gets the lowest ticket price they are eligible for.
  3. Think carefully about the order of your conditions. What if a customer is both a child and a student? What if they are a senior and a student? Which discount should apply? Test these combinations.

In the next lesson, you take this idea a step further. Instead of using a condition to choose which block runs once, you use a condition to repeat a block of code. That is where loops come in, starting with the while loop.