Conditions
Problem
The shipping that should not be there
An online shop promises free shipping on orders of €50 and up. Under €50, shipping is €4.99. The order is €62, and the program still adds shipping:
total = 62.0shipping = 4.99print(f"To pay: €{total + shipping}")To pay: €66.99The program runs every line, one after another. Here it has to choose: one line in one case, another line in another.
The idea
A comparison answers yes or no
First the program has to ask: is the total €50 or more? For this there are comparison operators. Their answer is not a number, but True or False: a value of type bool.
total = 62.0print(total >= 50)print(total == 50)print(total != 50)TrueFalseTrue| You write | It asks |
|---|---|
a > b, a < b |
greater, less |
a >= b, a <= b |
greater or equal, less or equal |
a == b |
are they equal |
a != b |
are they different |
Be careful: == compares, and = stores a value. total == 50 asks whether the total is 50, and total = 50 makes it 50.
Text in Python is compared with the same ==:
answer = "yes"yes = answer == "yes"print(yes)TrueMore precisely, if you are curious
Decimal numbers are rarely exactly equal. The computer stores 0.1 and 0.2 approximately, so their sum is not exactly 0.3:
print(0.1 + 0.2 == 0.3)print(0.1 + 0.2)False0.30000000000000004For decimal numbers, ask whether they are close enough: abs(a - b) < 0.000001. Comparisons with > and < do not have this problem.
The idea
if and else: one of two paths
Now the program can choose. if checks the condition after it. If it is true, it runs the block after the colon. If it is not, it runs the block after else:. The block is the lines indented by 4 spaces: there are no braces, the indentation says what is inside.
total = 62.0if total >= 50: shipping = 0else: shipping = 4.99print(f"Shipping: €{shipping}")Shipping: €0For an order of €18.50 the same program prints Shipping: €4.99. Only one of the blocks runs, never both.
else is not required. Without it, if the condition is not true, the block is simply skipped and the program continues after it.
More precisely, if you are curious
- In Python indentation is not for looks, it is part of the code. A line indented as much as the
ifitself is already outside the block and always runs. - The condition can be any value, not only
TrueorFalse. The number 0 and the empty text""count as false, everything else as true:
total = 0if total: print("There is a total")else: print("0 counts as false")0 counts as falseif total = 50:stops even before the program starts, withSyntaxError: Python does not allow=in a condition.
Try it
An order bigger than the stock
There are 3 items in the warehouse, and the customer orders 5.
What will the program print?
stock = 3ordered = 5if ordered > stock: print("Not enough in stock") ordered = stockprint(f"Sending {ordered} items")5 > 3 is true, so the block runs: it prints the message and lowers the order to 3. The last line is after the block and always runs.
The idea
elif: more than two paths
A teacher turns test points into a grade. There are four possibilities. Between if and else you put elif (short for else if):
points = 76if points >= 90: print("Excellent")elif points >= 75: print("Very good")elif points >= 50: print("Good")else: print("Fail")Very goodThe checks go from top to bottom. The first branch with a true condition runs, and the rest are skipped. 76 is not >= 90, but it is >= 75, so it is "Very good". The program never gets to >= 50, even though it is true too.
That is why the order matters: the strictest condition comes first. If points >= 50 were at the top, everyone with 50 points or more would get "Good".
points = 76if points >= 90: print("Excellent")elif points >= 75: print("Very good")elif points >= 50: print("Good")else: print("Fail")Step by step, in words
- points is 76.
- 76 >= 90? No. The "Excellent" branch is skipped.
- 76 >= 75? Yes. We go into the "Very good" branch.
- It prints "Very good".
- 76 >= 50 is true too, but it is not checked: the chain stops at the first true branch.
Try it
Find the bug
Everyone with 90 points or more gets "Excellent". A student with exactly 90 points gets "Very good". Which line is the bug on?
Pick the line with the bug.
points > 90 misses 90 itself. It has to be points >= 90. Bugs like this, "off by one", are common: when the condition is "from … and up", check what happens right at the boundary.
The idea
And, or, not
The cinema gives a discount ticket to children and to students. There are two conditions, and one is enough. You connect them with logical operators:
age = 16student = Falseif age < 18 or student: print("Discount ticket: €6")else: print("Ticket: €10")Discount ticket: €6In Python the operators are words:
a and bis true when both are true.a or bis true when at least one is true.not ais true whenais not true:not student.
Free shipping over €50 and only in the city is total >= 50 and in_city. A number is between 1 and 12 if month >= 1 and month <= 12. In Python the math notation works too, 1 <= month <= 12: it means the same thing.
month = 13print(1 <= month <= 12)print(month >= 1 and month <= 12)FalseFalseMore precisely, if you are curious
- If the left operand already decides the answer, the right one is not checked: with
False and …and withTrue or …. This is called short-circuit evaluation, and sometimes it protects you from an error:count != 0 and total / count > 10never divides by 0 (in Python, division by 0 stops the program withZeroDivisionError). andcomes beforeor, like*before+. When you mix them, add parentheses so it reads clearly:(a and b) or c.- A condition can also be inside another
if. That is a nestedif. This code is the same asif total >= 50 and in_city:
if total >= 50: if in_city: shipping = 0Try it
By 5 and by 7
What goes in the blank so the condition is true only for numbers divisible by both 5 and 7?
number = 35
if number % 5 == 0 number % 7 == 0:
print("Divisible by both 5 and 7")and: both checks have to be true. With or one would be enough, and 10 would pass too.The idea
The conditional expression if … else
Sometimes the whole if is only there to pick one of two values. There is a short form for that on one line, the conditional expression:
points = 76message = "You passed!" if points >= 50 else "You did not pass."print(message)You passed!It reads almost like a sentence: the value if it is true, if the condition, else the value if it is not. The same with if and else takes several lines, and here it is one.
In Java, C# and JavaScript the same thing is written with ? : and is called the ternary operator. Python has no ? :. Its equivalent is the conditional expression.
Use it to pick a value. If the program has to do different things in the two cases, write if.
More precisely, if you are curious
- The two values can be of different types: text in one case and a number in the other. The program runs, but afterward you do not know what the variable holds. Pick between values of one type.
points = 40result = "Passed" if points >= 50 else 0print(result)0- Conditional expressions can be nested inside each other, but code like that is hard to read. For three or more possibilities, write
elif.
The idea
match: choosing by value
The shop is open from 9:00 to 18:00 on weekdays, until 14:00 on Saturday, and it is closed on Sunday. If the day is a number (1 is Monday, 7 is Sunday), you compare it with several exact values. For this there is match:
day = 6match day: case 6: print("10:00–14:00") case 7: print("Closed") case _: print("9:00–18:00")10:00–14:00matchtakes the value after it and compares it with eachcasefrom top to bottom. The first one that matches runs.- After its
case,matchis done: the others do not run, and you do not needbreak. case _:is for all other values, like the lastelse.- Several values with the same action are written with
|in onecase:case 6 | 7:.
match has been in Python since 3.10. In older code the same thing is written with if and elif. For checks like "from 50 and up", write if.
More precisely, if you are curious
- A
casewith a bare name, for examplecase sunday:, does not compare with the variablesunday. It matches any value and stores it in that name. Here the day is 3, and the program prints "Closed":
sunday = 7day = 3match day: case sunday: print("Closed")ClosedIn a case, write the numbers and text themselves: case 7:, case "+":.
- In Java and C#,
switchcan also give a value.matchcannot: store the value in a variable in eachcase. An example with|:
day = 7match day: case 6 | 7: print("Weekend") case _: print("9:00–18:00")WeekendExercise
Programs that choose
Solve the tasks in your editor. Each number in the input is on a separate line. Try each solution with input that goes through the other branches too.
1. A cinema ticket. Read the age. Up to 6 years old you get in free, up to 17 the ticket is €6, up to 64 it is €10, from 65 up it is €5. A negative age is an error.
15The ticket is €62. A mini calculator. Read a number, an operation (+, -, * or /) and a second number. Pick the action with match on the text of the operation. You cannot divide by 0.
12/5Result: 2.43. A quadratic equation. Read a, b and c from ax² + bx + c = 0. The discriminant is D = b² − 4ac. If D is positive, there are two roots: (−b ± √D) / 2a. If D is 0, there is one root: −b / 2a. If D is negative, there are no real roots. If a = 0, the equation is not quadratic.
1-32x1 = 2.00, x2 = 1.004. A valid date. Read a day, a month and a year and say whether the date exists. Find the number of days in the month with match. February has 29 days in a leap year: divisible by 4 but not by 100, or divisible by 400.
2922023Invalid dateFor 29, 2, 2024 the output is Valid date.
More tasks
- Even or odd. For 7:
Odd. - Positive, negative or zero. For −5:
Negative. - Greater than 10. For 15:
Greater than 10. - Are they equal. Read two numbers. For 5 and 5:
Equal. - The bigger of two. Read two numbers and print the bigger one. Do it once with
ifand once with… if … else …. - Absolute value. Without
abs: if the number is negative, change its sign. - Yes or no. Read text. Print
Truefor "yes",Falsefor "no", andAnswer not understoodfor anything else. - By 5 and by 7. Say whether the number is divisible by both 5 and 7. For 35: yes, for 10: no.
- Three numbers in ascending order. Read three numbers and print them from the smallest to the biggest. For 7, 2, 5:
2 5 7. - The smallest and the biggest of five. Read five numbers into five variables. Remember the first one as both the smallest and the biggest, then compare each next one with it.
- Day of the week. Read a number from 1 to 7 and print the day:
1isMonday. For another number:No such day. Try it withmatch. - Age group. Up to 12 years old is a child, up to 19 a teenager, otherwise an adult.
- Season by month. December, January and February are winter, March to May is spring, and so on. For 4:
Spring. With match, put several values in one case: case 12 | 1 | 2: - Is it a triangle. Three sides make a triangle if the sum of any two is bigger than the third. For 3, 4, 5: yes, for 1, 2, 3: no.
- A grade in words. Read a grade from 2 to 6 and print
Fail,Average,Good,Very goodorExcellent. - Guess the animal. The program asks questions with a "yes" or "no" answer and guesses which animal you thought of. Start with a greeting and a short explanation of the game. You can ask all the questions and then decide with
elif, or ask only what you need with nestedifstatements. The questions:
| Question | If "yes" | If "no" |
|---|---|---|
| Does it fly? | a bird or an insect | go on |
| Does it have feathers? | a bird | if it flies, an insect |
| Does it swim? | if it does not fly: a fish or a small water mammal | go on |
| Does it meow? | a cat | not a cat |
| Does it have fur? | a dog, a cat or another mammal | a lizard or another reptile |
| Is it green? | if it does not fly and does not swim: a frog or a lizard | go on |
| Does it roar? | a cow or a lion | go on |
| Does it have a trunk? | an elephant | go on |
An example (the input is the answer to each question, in order):
nononoyesyesnononoThink of an animal. I will ask you 8 questions. Answer yes or no.Does it fly?Does it have feathers?Does it swim?Does it meow?Does it have fur?Is it green?Does it roar?Does it have a trunk?I think it is a cat.Test