Skip to content

Python lesson 4 of 9

Python Conditionals: if, elif, and else

Learn how Python decides what to run using if, elif, and else, plus comparison operators, and/or/not, truthiness, and the conditional expression.

Published · Every example on this page was run before it was published.

Every program you have written so far runs straight through from the first line to the last, doing the exact same thing every time. Real programs are not like that. A login screen shows a welcome message or an error message. A shopping cart applies a discount only when the total is big enough. A game ends only when your health reaches zero. To write programs like those you need a way to say "run this part only when something is true," and in Python that tool is the conditional statement.

What a Condition Is

A condition is any expression that Python can boil down to one of two values: True or False. Those two values are called booleans (named after the mathematician George Boole), and they are a real Python type just like numbers and strings are. You can store them in variables, print them, and combine them.

Think of a condition as a yes-or-no question asked about your data. A bouncer at a club door asks one question — "is this person eighteen or older?" — and the answer is always yes or no, never "maybe" or "sort of." Depending on the answer the bouncer takes one of two actions. Python works the same way: it evaluates the question, gets True or False, and picks a path.

The most common way to build a condition is with a comparison operator, which compares two values and produces a boolean:

| Operator | Question it asks | | --- | --- | | == | Are these two values equal? | | != | Are these two values different? | | > | Is the left value greater than the right? | | < | Is the left value less than the right? | | >= | Is the left value greater than or equal to the right? | | <= | Is the left value less than or equal to the right? |

Notice that equality is spelled with two equals signs. A single = means "store this value in this variable," which is a completely different job. Mixing them up is the single most common beginner error with conditionals, and we come back to it at the end of the lesson.

Comparisons work on their own, outside of any if statement. You can print them to see the boolean that comes out:

Python
age = 20

print(age > 18)
print(age == 20)
print(age != 20)
print(3 + 4 >= 10)
print("cat" == "Cat")
Output
True
True
False
False
False

That last line matters: string comparison in Python is case-sensitive, so "cat" and "Cat" are different values. Note also that Python evaluates the arithmetic 3 + 4 first and only then compares the result 7 against 10, which is why the answer is False.

Writing if, elif, and else

An if statement takes a condition and a block of code. If the condition is True, the block runs. If it is False, Python skips the whole block and carries on with the rest of the program.

Python
temperature = 31

if temperature > 28:
    print("It is hot today.")
    print("Remember to drink water.")

print("Have a good day.")
Output
It is hot today.
Remember to drink water.
Have a good day.

Look closely at the shape of that code. The line starting with if ends in a colon, and the two lines that belong to it are pushed in from the left margin. That push-in is called indentation, and in Python it is not decoration — it is the actual grammar of the language. Many other languages wrap conditional blocks in curly braces and treat indentation as a style choice. Python has no braces, so the indentation itself is what tells the interpreter "these lines belong to the if." The final print line sits back at the left margin, so it is outside the block and runs no matter what.

The standard is four spaces per level of indentation, and you must be consistent inside a single block. Every line in one block needs the same indentation, and mixing tab characters with spaces will make Python complain even when the code looks perfectly aligned on your screen.

To handle the false case, add an else block. It has no condition of its own — it simply catches everything the if did not:

Python
password = "hunter2"

if len(password) >= 8:
    print("Password accepted.")
else:
    print("Password is too short.")
Output
Password is too short.

The string "hunter2" has seven characters, so len(password) >= 8 is False and the else block runs. Exactly one of the two blocks runs — never both, never neither.

When you have more than two possible outcomes, use elif, which is short for "else if." You can chain as many elif blocks as you need between the opening if and the optional closing else:

Python
score = 83

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
else:
    grade = "F"

print("Your grade is", grade)
Output
Your grade is B

Python checks the conditions strictly from top to bottom and stops at the first one that is True. It never looks at the rest. That is why order matters enormously in an elif chain. Here is the same idea with the conditions written in the wrong order:

Python
score = 95

if score >= 70:
    print("C")
elif score >= 80:
    print("B")
elif score >= 90:
    print("A")
Output
C

A score of 95 really is greater than or equal to 70, so the very first branch wins and the better branches below are never reached. The fix is to put the most demanding condition first. When you build a chain of ranges, always read it from the top and ask whether an earlier branch could swallow a case meant for a later one.

Combining Conditions with and, or, not

Real decisions usually depend on more than one fact. Python gives you three logical operators to build compound conditions out of simpler ones:

  • and produces True only when the conditions on both sides are true.
  • or produces True when at least one side is true.
  • not flips a single boolean to its opposite.
Python
day = "Saturday"
weather = "sunny"

if day == "Saturday" and weather == "sunny":
    print("Perfect beach day.")

if day == "Saturday" or day == "Sunday":
    print("It is the weekend.")

if not weather == "rainy":
    print("No umbrella needed.")
Output
Perfect beach day.
It is the weekend.
No umbrella needed.

That third condition works, but if weather != "rainy": says the same thing more directly, and clearer code is better code. Save not for cases where the thing you are flipping is already a boolean, such as if not is_logged_in:.

These operators also have an important safety feature called short-circuiting. With and, if the left side is already False, Python does not even evaluate the right side — the overall answer cannot change. That lets you guard a risky operation behind a cheap check:

Python
items = []

if items and items[0] == "apple":
    print("The first item is an apple.")
else:
    print("No apple at the front.")
Output
No apple at the front.

An empty list has no position 0, so items[0] on its own would crash the program with an IndexError. Because the left side of the and is false for an empty list, Python never runs items[0] at all. Put your guard on the left and the thing that needs guarding on the right.

Truthiness: What Python Treats as False

The condition in an if statement does not have to be an actual boolean. Python will accept any value and decide for itself whether that value counts as true or false. This behaviour is nicknamed truthiness, and the values that count as false are called falsy.

The falsy values you will meet as a beginner are short and worth memorising:

  • the number 0 (and 0.0)
  • the empty string ""
  • the empty list []
  • the empty dictionary {} and the empty tuple ()
  • None, Python's word for "no value at all"

Everything else — any non-zero number, any string with at least one character, any list with at least one item — is truthy. The built-in bool() function shows you exactly how Python judges a value:

Python
print(bool(0))
print(bool(42))
print(bool(""))
print(bool("hi"))
print(bool([]))
print(bool([1, 2]))
print(bool(None))
Output
False
True
False
True
False
True
False

This is why the idiomatic way to ask "does this list have anything in it?" is simply to put the list in the condition:

Python
cart = []

if cart:
    print("Your cart has", len(cart), "items.")
else:
    print("Your cart is empty.")
Output
Your cart is empty.

Truthiness makes code short and readable when you genuinely mean "is this empty or missing?" It becomes a bug when zero is a meaningful value in your data, because Python cannot tell the difference between "the number zero" and "nothing was supplied." We will see exactly that trap in the Common Mistakes section.

Nesting Versus Flattening with elif

You can put an if statement inside another if statement, indenting it one more level. This is called nesting, and it is the right tool when the second question only makes sense after the first one has been answered:

Python
username = "ada"
password = "secret123"

if username == "ada":
    if password == "secret123":
        print("Welcome back, Ada.")
    else:
        print("Wrong password.")
else:
    print("Unknown user.")
Output
Welcome back, Ada.

Asking about the password only makes sense once you know the user exists, so nesting reads naturally here. But nesting is often used where it is not needed, and each extra level pushes your code further right and makes it harder to follow. Here is a classification written with three levels of nesting:

Python
n = 7

if n < 0:
    print("negative")
else:
    if n == 0:
        print("zero")
    else:
        if n < 10:
            print("small")
        else:
            print("large")
Output
small

Every one of those questions is asked about the same value, and only one answer can ever apply. That is precisely the situation elif exists for:

Python
n = 7

if n < 0:
    print("negative")
elif n == 0:
    print("zero")
elif n < 10:
    print("small")
else:
    print("large")
Output
small

Same result, half the indentation, and the four possible outcomes now line up in a column you can read at a glance. A good rule of thumb: if every nested if is testing the same variable, flatten the whole thing into one elif chain.

The Conditional Expression

Sometimes you only want to choose between two values, not two blocks of code. Writing a four-line if/else just to set one variable feels heavy, so Python offers a one-line form called a conditional expression (many programmers call it the ternary operator). It reads almost like English:

value_if_true if condition else value_if_false

Python
count = 1
label = "item" if count == 1 else "items"
print(count, label)

count = 4
label = "item" if count == 1 else "items"
print(count, label)
Output
1 item
4 items

The condition in the middle is evaluated first; if it is True the whole expression becomes the value on the left, and otherwise it becomes the value on the right. Because it is an expression rather than a statement, you can use it anywhere a value is allowed — inside a print() call, inside a list, or on the right-hand side of an assignment as above.

Keep it for short, simple choices. If either branch needs more than a brief value, or if you find yourself nesting one conditional expression inside another, go back to a regular if/else block; the extra lines buy real readability.

A Worked Example

This short program reviews a week of temperature readings, labels each one, counts the extremes, and finishes with a summary. It pulls together comparisons, an elif chain, a counter, and a conditional expression.

Python
readings = [18, 31, 0, -4, 25, 40]
hot_days = 0
cold_days = 0

for reading in readings:
    if reading >= 30:
        status = "hot"
        hot_days = hot_days + 1
    elif reading <= 0:
        status = "cold"
        cold_days = cold_days + 1
    else:
        status = "mild"
    print(reading, "->", status)

print("Hot days:", hot_days)
print("Cold days:", cold_days)

alert = "heat warning" if hot_days >= 2 else "no warning"
print("Status:", alert)
Output
18 -> mild
31 -> hot
0 -> cold
-4 -> cold
25 -> mild
40 -> hot
Hot days: 2
Cold days: 2
Status: heat warning

Here is what each part does. Line 1 stores the week's readings in a list, and lines 2 and 3 create two counter variables starting at zero — variables whose only job is to keep a running tally.

The for loop walks through the list one value at a time, and on each pass the variable reading holds the current value. Everything indented under the for line runs once per reading.

Inside the loop sits an elif chain. Python first asks whether the reading is at least 30. If so, it labels the day "hot" and adds one to hot_days. Only if that first question is False does Python ask the second one, whether the reading is zero or below. If both fail, the else block labels the day "mild". Exactly one of the three branches runs for each reading, so no day is ever counted twice.

The print on the last line of the loop body is indented to the loop's level but not to the if level, so it runs after whichever branch was chosen — that is indentation doing real work.

Notice the reading of 0. It is correctly labelled cold because the condition asks reading <= 0 explicitly. Had the code tried to use truthiness with something like if not reading:, the zero would have been treated as "no reading at all" rather than as a freezing day, which is exactly the kind of bug truthiness invites when zero is legitimate data.

After the loop finishes, the two print calls at the left margin report the totals. Finally the conditional expression picks one of two strings based on hot_days. Since two days hit 30 degrees or more, the condition hot_days >= 2 is True and alert becomes "heat warning".

Common Mistakes

1. Using = where == belongs. Assignment and comparison look similar and mean opposite things. The condition below is not a question at all, it is an attempt to store a value:

Output
x = 5

if x = 5:
    print("five")

Python refuses to run this and reports a SyntaxError. That is actually good news — the language catches the mistake for you instead of letting it hide. Read == out loud as "is equal to" and = as "gets," and the two stop blurring together:

Python
x = 5

if x == 5:
    print("five")
Output
five

2. Expecting or to spread across a comparison. In English "if the grade is A or B" is perfectly clear, so beginners write it the same way in Python. Python reads it very differently:

Python
grade = "C"

if grade == "A" or "B":
    print("Great job!")
else:
    print("Keep practicing.")
Output
Great job!

Python sees two entirely separate conditions joined by or: first grade == "A", which is False, and then the bare string "B", which is a non-empty string and therefore truthy. False or True is True, so the congratulation prints for a grade of C. Spell out the second comparison in full:

Python
grade = "C"

if grade == "A" or grade == "B":
    print("Great job!")
else:
    print("Keep practicing.")
Output
Keep practicing.

For a longer list of options, if grade in ("A", "B", "C"): is shorter and reads well. And while we are on the subject of comparisons that trip people up: Python genuinely supports chained comparisons, so 0 <= n <= 35 is valid and means exactly what it looks like — n is at least 0 and at most 35. Most languages do not allow that, which cuts both ways. If you come from one of them you may write it out the long way unnecessarily, and if you rely on the chain in Python you should remember it only works for comparison operators, never as a way to chain or around a single value.

3. Leaning on truthiness when you mean "is missing." Suppose a discount is either a number or None when the customer supplied nothing:

Python
discount = 0

if not discount:
    print("No discount was supplied.")
else:
    print("Discount is", discount)
Output
No discount was supplied.

A discount of zero is a real answer, but 0 is falsy, so the program reports it as missing. Ask the precise question instead. is None checks whether the value is literally Python's None object, and nothing else can accidentally match it:

Python
discount = 0

if discount is None:
    print("No discount was supplied.")
else:
    print("Discount is", discount)
Output
Discount is 0

Use bare truthiness when "empty" and "missing" should genuinely be treated the same way, and is None whenever zero, an empty string, or an empty list could be meaningful data. Note that it is is None, not == Noneis asks whether two names refer to the very same object, which is the right question for a one-of-a-kind value like None.

4. Getting the indentation wrong. Because indentation defines the block, a line in the wrong column changes the meaning of your program or stops it running entirely:

Output
if score > 50:
print("You passed.")

Python expects an indented block after the colon and raises an IndentationError when it does not find one. The opposite version is sneakier, because it runs:

Python
score = 20

if score > 50:
    print("You passed.")
print("Great work!")
Output
Great work!

The congratulation was meant to belong to the if, but it sits at the left margin, so it prints for a failing score too. Nothing errors — the program is simply wrong. Whenever a message appears when it should not, check the column it starts in before you check anything else.

Next Steps

Try the linked practice problem, balanced-parentheses. It asks you to scan through a string and decide whether every opening bracket has a matching closing one, which means making a decision about every single character — if for an opener, elif for a closer, and a careful check for the mismatch case. It is an excellent exercise in getting an elif chain in the right order.

Before that, open the Python playground and experiment. Change the values in the grading chain and confirm you can predict the branch that runs. Print bool() of a few odd values, such as bool(" ") and bool("0"), and see whether the results surprise you. Getting a feel for which conditions are true is the fastest route to writing them confidently.

Write it yourself

Reading about code and writing it are different skills. These exercises practise exactly what this lesson covered; they run in this tab and need no account.

When you want a harder one

Interview-style problems graded against hidden tests — a big step up from the exercises. Come back to these when the ideas in this lesson feel comfortable rather than new.