Chapter 15: Conditional and Control Statements
The bell in Anaya’s school does not ring by itself. Every morning her teacher, Mr. Rao, watches the clock, and at 7:40 he presses the button. On Sundays he does not press it at all. On examination days he presses it twice — once as a warning, once for the start.
This year the school fitted a small computer to do that job. The computer has to follow the same choices Mr. Rao followed. If it is Sunday, ring nothing. If it is an examination day, ring twice. Otherwise, ring once. And each time it rings, the striker must move for exactly six beats — not five, not seven.
Look at that carefully. Two different kinds of instruction are hiding inside it. One kind picks a path: do this, or else do that. The other kind repeats a job — a fixed number of times, or until something changes. The path the small computer follows is shown in Fig. 15.0-1.
Almost every useful program you will write is built out of these two ideas.
Diagram
Fig. 15.0-1 – simple flowchart of the school bell controller; start at top, a diamond labelled “Is it Sunday?” with a “yes” arrow going straight to Stop and a “no” arrow going down to a second diamond labelled “Is it an exam day?”; “yes” leads to a box “ring twice”, “no” leads to a box “ring once”; from each ring box a small loop with a curved arrow back on itself labelled “6 beats”, then an arrow to Stop
This chapter will answer all five of these questions.
15.1 Why a Program Needs to Choose
Every program you have written so far has run in a straight line. Python starts at the first line, does it, moves to the second, does that, and carries on until the last line. Nothing is skipped and nothing is repeated.
name = input("Enter your name: ")
print("Welcome,", name)
print("Have a good day")This is fine for a task that is the same every single time. Printing a welcome message is such a task.
But most real tasks are not like that. Think of the light in a school corridor that is fitted with a light sensor. It does not switch on every time you walk past. It switches on only when the corridor is dark. The same walk gives two different results depending on one piece of information.
A ceiling fan with a temperature controller behaves the same way. If the room is above a set temperature, run faster. If it is below, run slower. The rule stays the same; the outcome changes.
Two questions a program keeps asking
Look closely at those two examples and you will find two separate needs.
The first is a choice. Should I do this at all? The corridor light has to check the darkness before switching on. A program that cannot make a choice can only ever do one fixed thing.
The second is repetition. Should I do this again? The bell striker in the chapter opener has to move six times, not once. Writing the same instruction six times would work, but writing it two hundred times would not.
The order in which the statements of a program actually run is called its control flow. Up to now your control flow has been a straight line. In this chapter you will learn to bend it — to branch it into two paths, and to bend it back on itself so a part runs again.
You can see the difference in Fig. 15.1-1.
Diagram
Fig. 15.1-1 – two simple flow sketches side by side. Left, labelled “straight-line flow”: three boxes stacked with downward arrows, Start → Step 1 → Step 2 → Step 3 → Stop. Right, labelled “branching flow”: Start → Step 1 → a diamond labelled “Is it dark?” with a “yes” arrow to a box “switch light on” and a “no” arrow bypassing that box; both arrows join again and go to Stop
What a condition is
To choose a path, the program needs something it can test. That something is a condition — an expression that works out to either True or False, and nothing else.
You have already met the comparison operators that produce such values: >, <, >=, <=, == and !=. An expression like temperature > 30 is not a number. It is a plain yes-or-no answer written as True or False.
A statement that uses a condition to pick which block of code runs is called a conditional statement. Sections 15.3 onward deal with these.
One honest limit
A condition can only answer with True or False. It cannot answer “almost”, “roughly”, or “it depends”. If you ask whether the temperature is above 30, then 30.1 is above and 30.0 is not, with nothing in between. The sharpness is useful when the rule really is sharp — a pass mark, a voting age, a battery level below which a robot must return to charge. It is a poor fit when the real-world idea is fuzzy, such as deciding whether a room feels warm. Programs handle fuzzy ideas by turning them into sharp cut-offs, and the person writing the program has to choose those cut-offs carefully.
15.2 Blocks and Indentation in Python
Before a program can choose a path, it needs a way to say which lines belong to that path. A choice is rarely one line long. “If the corridor is dark, switch on the light and note the time” is two instructions that must be treated as one group.
A group of lines that Python treats as a single unit is called a block.
How Python marks a block
Many programming languages wrap a block in curly brackets. Python does not. It uses the blank space at the start of a line instead. Shifting a line to the right is called indentation, and in Python indentation is not decoration — it is what tells Python where a block begins and ends.
The rule has two parts.
First, the line that introduces a block ends with a colon. Second, every line of that block is indented by the same amount. The block ends at the first line that comes back out to the left. This is shown in Fig. 15.2-1.
Diagram
Fig. 15.2-1 – three lines of code drawn as plain bars. Top bar flush left, ending with a large colon, labelled “header line”. Below it, two bars shifted right by four spaces, with a tall square bracket beside them labelled “the block”. A fourth bar back at the far left, labelled “outside the block”. A small ruler mark between the left edge and the indented bars, labelled “4 spaces”
Python allows any consistent amount of indentation, but the accepted style is four spaces, and that is what this book uses everywhere. Most editors insert four spaces when you press the Tab key.
Seeing indentation change the meaning
The short program below prints a result for a student. Two of its lines belong to a block and one does not.
The first two print() lines are indented, so they form the block that belongs to the choice. The third is flush with the left margin, so it is outside the choice and runs whatever the marks are.
Now imagine shifting that third line four spaces to the right as well. It would join the block. With marks = 72 the output would look exactly the same, so you might think nothing had changed. But with marks = 30 the original program still prints Result printed, while the changed one prints nothing at all. Indentation is a real instruction, and a mistake in it does not always show up straight away.
Blocks inside blocks
A block can hold another block. The inner one is simply indented further — eight spaces instead of four, then twelve, and so on. You will see this in Section 15.3.4 and again in Section 15.4.4, where one choice sits inside another and one loop sits inside another.
Keep the nesting shallow where you can. Code that is indented five or six levels deep is hard to read and hard to correct, even for the person who wrote it.
15.3 Conditional Statements
You now have both pieces you need. A condition gives a True or False answer, and a block groups the lines that should run. A conditional statement joins the two: it tests a condition and runs a block only when the answer is True.
Python’s conditional statements are built from three keywords — if, elif (short for “else if”) and else. Every conditional statement you write in this chapter is some arrangement of these three.
Three shapes of a decision
It helps to notice that not all decisions have the same shape.
Some decisions have one path. A message appears when a student has passed, and nothing happens otherwise. There is a block to run, or there is nothing to run.
Some have two paths. A student has either passed or failed, and a message is needed for both. Exactly one of the two blocks will run — never both, never neither.
Some have many paths. A grade might be A, B, C, D or F. Five paths, still exactly one of them taken. Fig. 15.3-1 shows the three shapes together.
Diagram
Fig. 15.3-1 – three small flowcharts in a row, each starting from a downward arrow. Left, labelled “one path”: a diamond with a “yes” arrow into a single box and a “no” arrow going straight past it; both join at the bottom. Middle, labelled “two paths”: a diamond with “yes” into a left box and “no” into a right box, both joining at the bottom. Right, labelled “many paths”: a vertical chain of three diamonds, each with a “yes” arrow going right into its own box and a “no” arrow going down to the next diamond, with a final box at the bottom labelled “none matched”; all boxes join at the bottom
The sections that follow take these one at a time — if for one path, if-else for two, and the if-elif-else ladder for many. After that come two more arrangements: one decision written inside another, and the match statement, which is a tidier way of writing certain many-path decisions.
15.3.1 The if Statement
Start with the simplest kind of choice — the one-path decision.
A small wheeled robot built by a school club carries a sensor that measures how far away the nearest object is. The rule is short: if that object is closer than 20 cm, print a warning. If it is further away, say nothing and carry on. There is only one block of work here, and it may or may not be needed.
The method in words is short enough to write out first.
The general form
Python writes this with the if keyword. The if statement runs its block once when the condition is True, and skips the block completely when the condition is False.
if condition:
# this block runs only when the condition is TrueThree details matter. The word if comes first, the condition follows it, and the line ends with a colon. The block underneath is indented by four spaces, as you saw in Section 15.2.
Here is the robot check written as a working program. The measured distance is stored in a variable first, so you can change one number and try the program again.
With distance set to 15, the condition distance < 20 is True, so the warning is printed. Change the first line to distance = 45 and the condition becomes False. The indented line is skipped, and the only output is Check complete.
One limit worth knowing
An if statement on its own can say what to do when the condition holds, but it has no place to put the work needed when the condition does not hold. For the robot that was fine — nothing had to happen. When both outcomes need an action, you need the two-path form in Section 15.3.2.
15.3.2 The if-else Statement
Many decisions need an action on both sides.
A school has an overhead water tank with a level sensor. When the water level falls below 30 per cent of full, the pump must be switched on. When it is at or above 30 per cent, the pump must be switched off. Neither outcome is “do nothing” — something has to happen either way.
An if statement alone cannot express this neatly. You could write two separate if statements, one for each case, but then Python would test the same fact twice and you would have to keep the two conditions in step by hand. Python offers a better tool.
The general form
The if-else statement attaches a second block to the first. Python tests the condition once. If it is True, the if block runs. If it is False, the else block runs instead. Exactly one of the two blocks runs — never both, and never neither.
if condition:
# this block runs when the condition is True
else:
# this block runs when the condition is FalseNotice that else sits at the same indentation as if, and it too ends with a colon. It carries no condition of its own, because it simply catches everything the if did not.
Here is the tank rule as a program.
With level set to 22 the condition is True, so only the first message appears. Set level to 30 and the condition 30 < 30 is False, so the second message appears instead. A level of exactly 30 counts as fine, because the condition asks for less than 30 and not less than or equal to. Where you place that boundary is your decision as the programmer, and it should match the rule the school actually wants.
Comparing the two forms
Table 15.1 sets the two statements side by side.
One limit worth knowing
if-else splits the work into exactly two paths. The moment a problem has three or more outcomes — a pump that runs fast, runs slow, or stays off — two blocks are not enough, and you need the form in the next section.
15.3.3 The if-elif-else Ladder
A city bus charges by distance. Up to 5 km the fare is ₹10. Beyond that and up to 10 km it is ₹15. Beyond that and up to 20 km it is ₹25. Anything longer costs ₹40.
That is four outcomes, and only one of them can apply to a single journey. Two blocks are not enough.
You could write four separate if statements. It would work, but it would be clumsy: Python would test all four conditions even after the right one had been found, and every condition would have to spell out both its lower and upper limit. Python offers a form built exactly for this shape.
The general form
The elif statement — short for “else if” — lets you hang extra conditions under an if. Together they form what is usually called an if-elif-else ladder.
if condition1:
# runs when condition1 is True
elif condition2:
# runs when condition1 is False and condition2 is True
elif condition3:
# runs when the two above are False and condition3 is True
else:
# runs when none of the conditions above is TruePython works down the ladder from the top. The moment a condition comes out True, its block runs and the whole statement finishes — the conditions below it are never even looked at. If none is True, the else block runs.
You may write as many elif branches as the problem needs. The final else is optional; leaving it out simply means that when nothing matches, nothing runs.
The bus fare as a program
Follow what happened. The first condition asks whether 12 is at most 5 — False, so the block is skipped. The second asks whether 12 is at most 10 — also False. The third asks whether 12 is at most 20 — True, so fare becomes 25 and Python leaves the ladder. The else branch is never reached.
Notice that the third condition did not have to say “more than 10 and at most 20”. It only had to rule out 20 and above, because a journey of 10 km or less would already have been caught higher up. This is what makes the ladder shorter than four separate if statements.
15.3.4 Nested if Statements
Sometimes a second question only makes sense once the first one has been answered.
Think about the wheeled robot from Section 15.3.1 again. Before it moves anywhere, it checks its battery. If the charge is too low, it must go back to the charging point, and nothing else matters — there is no point asking about the path ahead, because the robot is not going that way. Only when the charge is healthy does the second question arise: is the way in front clear?
That is a decision inside a decision. Writing one conditional statement inside the block of another is called nesting.
Fig. 15.3.4-1 shows the shape of the robot’s decision.
Diagram
Fig. 15.3.4-1 – flowchart. Start at top, arrow into a diamond labelled “battery at least 20%?”. The “no” arrow goes right into a box “return to charger”. The “yes” arrow goes down into a second diamond labelled “clearance more than 20 cm?”, drawn inside a dotted rectangle labelled “runs only when the battery is fine”. From this diamond, “yes” leads to a box “move forward” and “no” to a box “stop and turn”. All three action boxes join at the bottom and go to Stop
Writing it in Python
The inner statement is an ordinary if or if-else. The only new thing is the indentation: because it sits inside the outer block, its own header line is indented four spaces, and its blocks are indented eight.
Read it from the outside in. The battery is 65, so the outer condition is True and Python enters the outer block. Inside, the clearance of 12 cm is not more than 20, so the inner else runs. Change battery to 8 and the outer condition becomes False — the whole inner statement is skipped without ever being tested, and only the charger message is printed.
Nesting or a ladder?
Beginners often use a nested if where an if-elif-else ladder would read better, and the two are easy to confuse. Table 15.2 separates them.
The useful test is to ask whether the second question would still make sense if the first were answered the other way. If it would not, you need nesting. If it would, a ladder is almost always clearer.
Two levels of nesting are common and readable. Beyond three, it is worth stopping to rework the logic.
15.3.5 Case and Switch: the match Statement
Some many-path decisions are not about ranges at all. They are about a single value matching one of a fixed set of choices.
A robot receives one-letter commands from a control app: F for forward, B for back, L for left, R for right. Anything else is a mistake and should be reported. There are no slabs and no boundaries here — just five separate cases, each compared against the same variable.
An if-elif-else ladder handles this perfectly well, but the variable name has to be repeated in every branch: if command == "F":, then elif command == "B":, and so on. Many programming languages provide a tidier form for exactly this shape, usually called a switch statement with a list of cases inside it.
The general form
Python’s version is written with the keywords match and case. The match statement compares one value against a list of cases and runs the block belonging to the first case that matches.
match value:
case pattern1:
# runs when the value matches pattern1
case pattern2:
# runs when the value matches pattern2
case _:
# runs when none of the cases above matchedThe match line ends with a colon, and each case line does too. The single underscore, _, is a wildcard that matches anything, so case _ plays the same part as else in a ladder.
Python compares command with "F", then "B", then "L", finds the match, prints the message and leaves the statement. The remaining cases are not tested.
Two cases can share a block by joining their patterns with a vertical bar, so that both a capital and a small letter are accepted:
case "F" | "f":
print("Move forward")When to use which
Table 15.3 compares the two many-path forms.
For a fixed list of values — command letters, menu numbers, day names — match reads more clearly. For ranges and for conditions that test different things, the ladder is the right tool. Neither can do anything the other cannot; the choice is about which one a reader will understand faster.
15.3.6 Shorthand Conditional Statements
Some decisions are so small that spreading them over four lines makes them harder to read, not easier. Python offers two short forms for these. Both are conveniences — neither can do anything the full forms in the earlier sections cannot.
An if statement on one line
When the block under an if is a single short statement, it may be written on the same line, straight after the colon.
marks = 91
if marks > 90: print("Distinction")Output:
Distinction
This is the same if statement you already know, just written more compactly. It is worth using only when the whole line stays short and obvious. As soon as there is more than one statement to run, the block must go back onto its own indented lines.
The conditional expression
The second short form is more useful. Often an if-else exists only to put one value or another into a variable:
if temperature > 40:
advice = "Stay indoors"
else:
advice = "Fine to go out"Four lines, and the variable name is written twice, for what is really a single choice between two values. Python lets you write that choice as one expression.
A conditional expression picks between two values in a single line. It is sometimes called the ternary operator, because it works on three parts: the two values and the condition between them.
value_if_true if condition else value_if_falseRead it in the order it is written: this value, if the condition holds, otherwise that value. The condition sits in the middle, which takes a little getting used to.
The condition temperature > 40 is False, so the expression takes the value after else and stores it in advice. The four-line version above and this one behave identically.
Knowing when not to use it
Shorthand is a good servant and a poor master. A single, short conditional expression is easy to read. One that stretches past the width of the screen, or one written inside another, is much harder to follow than the plain if-else it replaced — and code that is hard to follow is code that hides mistakes.
Use the short forms for small, obvious choices. Everywhere else, the full form is the better piece of writing.
15.4 Loops: Doing the Same Work Again
The school bell in the chapter opener has to strike six times. Written as straight-line code, that is six identical lines:
print("beat")
print("beat")
print("beat")
print("beat")
print("beat")
print("beat")It works. But if the school later decides on eight beats, six lines have to become eight. If a program had to print a message for each of 600 students, nobody would type 600 lines. And if the striker had to keep moving until a sensor said the bell had stopped ringing, the number of lines could not be worked out in advance at all.
Repetition needs its own kind of statement.
What a loop is
A loop is a statement that runs a block of code again and again. Each single run of the block is called one iteration.
The idea is not new to you. A teacher marking a set of answer papers does the same few steps for every paper: read, mark, write the total, put it on the pile. The steps do not change; only the paper does. That is exactly what a loop does — it holds the steps still and lets the data move through them.
Fig. 15.4-1 shows the shape.
Diagram
Fig. 15.4-1 – flowchart of a loop. Start at top, arrow down into a diamond labelled “should the block run again?”. The “no” arrow leaves to the right and goes to Stop. The “yes” arrow goes down into a box labelled “run the block once”, and from the bottom of that box a curved arrow travels back up to the left side of the diamond, labelled “repeat”
Notice where the test sits. The question is asked before each iteration, not after. If the answer is no the very first time, the block does not run even once.
Two ways of saying “again”
Look back at the three situations at the start of this section and you will find two different kinds of repetition hiding in them.
In the first, the number of repeats is known before the loop starts. Six beats. Six hundred students. Every letter in a word. You could count them out in advance.
In the second, the number is not known. Keep asking for a password until the right one is typed. Keep the striker moving until the sensor reports silence. The loop stops when something changes, and there is no way to say beforehand how many rounds that will take.
Python has a loop for each. The while loop in Section 15.4.1 repeats as long as a condition stays True, which fits the second kind. The for loop in Section 15.4.2 walks through a collection of items one at a time, which fits the first. Section 15.6 compares them properly, once you have used both.
The mistake that never ends
Every loop needs some way of eventually stopping. A loop whose stopping condition never becomes False is called an infinite loop, and it will keep running until you force the program to close. Press Ctrl and C together in the terminal to stop a program that has run away.
Infinite loops are the commonest beginner’s mistake with while, and Section 15.4.1 shows exactly how they happen.
15.4.1 The while Loop
A pump is filling the school’s overhead tank. Nobody can say in advance how many minutes it will take, because that depends on how empty the tank was when the pump started. What can be said is when to stop: keep pumping while the level is below full.
That is the shape the while loop was made for. It repeats a block for as long as a condition stays True.
The general form
while condition:
# this block runs again and again while the condition is TrueThe line looks almost exactly like an if. The difference is what happens at the end of the block: an if moves on, while a while goes back to the top and tests the condition again.
Python checks the condition before every iteration, including the first. So if the condition is already False when the loop is reached, the block never runs at all.
Three parts that must all be there
Nearly every while loop has three moving parts, and leaving out any one of them breaks it.
First, something must be set up before the loop starts — a starting level, a starting count. Second, the condition must be built from something that can change. Third, the block must actually change it, or the condition will stay True for ever.
The method for the tank is written out below.
Table 15.4 lists what the two variables hold at the end of each iteration. Reading down the last column shows why the loop stopped when it did.
The final message is printed once, after the loop, because it is not indented into the block.
15.4.2 The for Loop
Go back to the school bell. Six beats, every time. The count is fixed and known before anything starts.
A while loop could do it — set a counter to 1, keep going while the counter is at most 6, add 1 each round. But that means writing three separate things and keeping them in step, when all you really wanted to say was “do this six times”. Python has a loop that says exactly that.
The for loop walks through a collection of items, one at a time, running its block once for each item.
The general form
for variable in collection:
# this block runs once for each item in the collectionThe name written after for is the loop variable. Python sets it to the first item, runs the block, sets it to the second item, runs the block again, and so on. When the items run out, the loop ends by itself. You never have to write a condition, and you never have to remember to increase a counter — that is the whole point of the for loop.
Anything a for loop can walk through is called an iterable: an object able to hand over its items one at a time. Lists, tuples, strings, dictionaries and ranges are all iterables, and Section 15.4.3 takes them one by one.
Counting with range()
For plain counting there is a built-in tool called range(), which produces a run of whole numbers without your having to type them out.
range() can be given one, two or three numbers, as Table 15.5 shows.
One rule runs through the whole table: the stopping number is never included. range(5) gives five numbers but never reaches 5. This catches almost everybody once, so it is worth saying twice — the first number is included, the last is not.
The range starts at 1 and stops before 7, so the loop variable beat takes the values 1 to 6 — six iterations, one line each. If the school later wants eight beats, one number changes and nothing else does.
Where the two loops sit
A for loop knows how many iterations it will run before it starts, because the collection is already there to be counted. A while loop does not, because it only ever looks one condition-test ahead. That is the real difference between them, and Section 15.6 returns to it.
15.4.3 Looping Over Lists, Tuples, Strings and Dictionaries
range() is useful, but the collections you met in Chapter 13 are far more interesting to walk through. A for loop treats them all the same way: hand me your items one at a time, and I will run my block for each.
This section takes the four you know — list, tuple, string and dictionary — and shows what the loop variable holds in each case.
Looping over a list
A list holds items in order, and can be changed after it is made. Looping over it gives you the items themselves, not their positions.
Here a robot has stored five distance readings taken as it moved along a corridor.
The loop variable reading is 45 in the first iteration, 32 in the second, and so on. Notice the if-else sitting inside the loop: the same test is applied to every item, but the answer differs from one item to the next. Conditions inside loops are the commonest and most useful combination in the whole of programming.
Looping over a tuple
A tuple also holds items in order, but once made it cannot be changed. That makes it the right choice for a fixed list that should not be edited by accident — the joints of a robot arm, for instance.
As far as the loop is concerned, nothing has changed from the list. Round brackets in place of square ones is the only visible difference.
Looping over a string
A string is a sequence of characters, so a for loop hands over one character at a time — letters, digits, punctuation and spaces alike.
letter.lower() gives back the small-letter version of the character, so a capital O would be counted too. The variable count has to be set to 0 before the loop, because it must survive from one iteration to the next.
Looping over a dictionary
A dictionary stores pairs — a key and the value that goes with it. Looping over the dictionary itself gives you the keys, and you can use a key to look up its value. Looping over .items() gives you both at once, which is usually neater.
The second loop has two names after for, separated by a comma, because .items() hands over a pair each time. Python fills the first name with the key and the second with the value.
From Python 3.7 onwards a dictionary keeps its items in the order they were added, so the loop visits them in that order. Older versions gave no such promise.
15.4.4 Nested Loops
A school hall is being labelled for an examination. There are 3 rows of seats, and each row has 4 seats. Every seat needs a label such as R2S3, meaning row 2, seat 3.
One loop is not enough here. Walking through the rows gives you 3 iterations; walking through the seats gives you 4. What you actually need is every seat in every row — 4 seats, repeated for each of the 3 rows.
That is a loop inside a loop, and it is called a nested loop.
The second sentence of that definition is the whole idea. Fig. 15.4.4-1 shows it.
Diagram
Fig. 15.4.4-1 – a large rounded rectangle labelled “outer loop: rows 1 to 3” containing a smaller rounded rectangle labelled “inner loop: seats 1 to 4”, which in turn contains a small box labelled “print one seat label”. A curved arrow inside the small rectangle loops back on itself labelled “4 times”, and a larger curved arrow inside the big rectangle loops back on itself labelled “3 times”. To the right, a short note reads “3 × 4 = 12 labels”
Writing it in Python
The inner loop is an ordinary for loop. It simply lives inside the outer loop’s block, indented one more level.
Two small details do the tidying. Normally print() moves to a new line when it finishes; end=" " tells it to put a space there instead, so the four labels of a row stay side by side. The bare print() on the last line has nothing to print, so all it does is move to the next line — and because it is indented at the outer level, it runs once per row, after the inner loop has finished.
Follow the order of events. The outer loop sets row to 1 and enters its block. The inner loop then runs completely, giving seats 1, 2, 3 and 4. Only then does print() end the line, and only then does the outer loop set row to 2 and start the inner loop all over again.
The cost of nesting
Nested loops multiply. Three rows and four seats is 12 iterations, which is nothing. But a nested loop over a list of 1000 items inside another loop over the same 1000 items is a million iterations, and that is enough to make a program noticeably slow.
Two levels are common and perfectly reasonable. Beyond that, it is worth asking whether the work can be done another way.
15.5 Changing the Flow of a Loop
So far every loop you have written has been all-or-nothing. It starts, it runs its block for every item or until its condition fails, and then it ends. The block itself has had no say in the matter.
Real tasks are not always so patient.
A robot walking through a list of stored readings may find an obstacle at the second reading. There is no sense in checking the remaining three — the answer is already known, and carrying on wastes time.
A program totalling a set of readings may come across one that is clearly faulty, perhaps a negative distance. It should ignore that single reading and carry straight on with the rest, not abandon the whole job.
And sometimes a block is needed that does nothing at all — a branch you have decided to leave empty for now.
Python has one small keyword for each of these three situations: break, continue and pass. They are usually called loop control statements, because they change the normal flow of a loop from inside it.
Fig. 15.5-1 shows where each one sends the program.
Diagram
Fig. 15.5-1 – a tall rounded rectangle labelled “the loop”, with a diamond “condition?” at the top and a block of three stacked statement bars below it, and a return arrow from the bottom of the block back up to the diamond. Three coloured arrows leave the middle bar. One, labelled “break”, exits the rectangle entirely and points to a box outside marked “next statement after the loop”. One, labelled “continue”, curves back up to the diamond, skipping the bars below it. One, labelled “pass”, is drawn as a very short arrow to the very next bar, with the note “does nothing”
The three sections that follow take them one at a time. All three work in a while loop and in a for loop, in exactly the same way.
15.5.1 The break Statement
A robot has stored five distance readings taken at five points along a corridor. It has to report the first point where something is closer than 20 cm.
The word first changes everything. Once that point is found, the remaining readings tell you nothing you need. Checking them anyway is not wrong, but it is wasted work — and in a program that searches a list of ten thousand items, wasted work is worth avoiding.
The break statement ends a loop immediately. The rest of the current iteration is abandoned, no further iterations happen, and the program carries on with the first statement after the loop.
Searching until something is found
The list holds five readings, but the loop ran only three times. At step 3 the condition became True, the message was printed, and break sent the program straight out of the loop. The readings 33 and 8 were never looked at — and note that 8 is closer still, which is exactly the point: the program was asked for the first close reading, not the closest one.
One loop at a time
In a nested loop, break leaves only the loop it is written in — the innermost one. The loop outside it carries on to its next iteration as though nothing had happened.
When not to reach for it
break is easy to overuse. A loop with three or four break statements scattered through it becomes hard to read, because there is no longer one clear place where the loop ends.
Where the loop’s own condition can express the stopping rule, let it. break earns its place when the rule can only be discovered inside the block — as with the search above, where you cannot know which reading is the first close one until you look at it.
15.5.2 The continue Statement
Sensors are not perfect. A distance sensor that receives no echo often stores a value that could never be real — a negative distance, say. Such a value is not a measurement at all, and adding it to a total would drag the answer away from the truth.
The job here is different from the search in Section 15.5.1. Nothing has been found and the loop should not stop. One item simply has to be left out, and the rest handled as usual.
The continue statement abandons the current iteration only. Everything below it in the block is skipped, and the loop moves straight on to its next round.
Ignoring the faulty readings
The loop ran all six times — continue never shortens a loop. On the second and fourth iterations it jumped past the two adding lines, so those readings changed neither total nor good. The other four were counted normally.
The average is the total divided by how many values went into it, which is why good had to be counted separately. Dividing by 6 would have treated the two rejected readings as though they were zeros.
\(\text{average} = \dfrac{\text{total of the good readings}}{\text{number of good readings}}\)
This matches the 34.0 the program printed. Python shows 34.0 rather than 34 because dividing with / always produces a float.
15.5.3 The pass Statement
Python has a rule that catches every beginner sooner or later: a block can never be empty. Write else: with nothing indented under it and the program will not run at all. Python reports an IndentationError, because it reached the end of a block that had not begun.
Most of the time that rule is helpful — an empty block is usually a line you forgot to write. But sometimes an empty block is exactly what you want.
You may be sketching out the shape of a program and want the branches in place before the code that fills them. Or you may have a case that genuinely calls for no action, and you want a reader to see that the case was thought about and deliberately left alone.
The pass statement exists for these moments. It does nothing whatsoever. Its only job is to be a statement, so that a block which has to exist is not empty.
A branch left deliberately empty
A robot is working through a list of stored commands. Three letters are understood. Anything else is to be ignored quietly for now, until the team decides what an unknown command should do.
The letter X matched none of the three branches, so the else ran — and did nothing, exactly as intended. The loop then carried on to B as usual.
You could delete the whole else branch and the output would be identical. Many programmers would. Keeping it, with a comment, says something the shorter version does not: that unknown commands were considered, and that ignoring them is a decision rather than an oversight.
Telling the three apart
Table 15.6 sets out what each of the three keywords does.
That last row matters. break and continue only make sense inside a loop, and Python reports a SyntaxError if you write them anywhere else. pass may appear in any block at all — inside an if, inside a case, and, as you will see in Chapter 16, inside a function that has not been written yet.
15.6 Choosing Between while and for
You have now used both loops, so the obvious question can be asked properly: given a job that needs repeating, which one should you reach for?
Start by noticing that the two loops overlap. Many tasks can be written either way.
Identical results. But look at how much each version had to be told. The for loop needed one line: where to start, where to stop, what step. The while loop needed three separate lines — a starting value, a condition, and an increase — spread over three different places in the program, and if any one of them is wrong the loop misbehaves.
That is the practical difference. Where the sequence of values is known in advance, a for loop states it once and cannot lose count.
The real distinction
Table 15.7 sets the two loops side by side.
The row about infinite loops is worth pausing on. A for loop walking a list of five readings will stop after five iterations whatever you do inside it. A while loop offers no such promise, which is why Section 15.4.1 insisted on finding the line that moves the condition towards False.
A rule of thumb
Ask yourself one question before writing the loop: could I say now how many times this must run?
If the answer is yes — six bell beats, every item in a list, every character in a word, every subject in a dictionary — use a for loop.
If the answer is no — keep asking for input until it is valid, keep pumping until the tank is full, keep trying until a sensor changes — use a while loop.
15.7 Putting Conditions and Loops to Work
Conditions and loops are rarely used on their own. Almost every useful program is a loop with a condition inside it, and this section works through three examples of that pattern. Read each method first, then the code.
Finding the highest and lowest in a set of readings
A weather project stores the day’s highest temperature for four cities. The task is to report which city was hottest and which was coolest.
You cannot answer this by looking at one city. You have to go through the whole set, remembering the best answer so far and replacing it whenever something better turns up. That “best so far” idea appears again and again in programming.
The two starting values, −100 and 100, are chosen to sit outside any temperature that could really be recorded, so the very first city is bound to replace both of them. That trick works, but it depends on knowing the range of the data in advance — which is an honest weakness. With a quantity whose range you cannot guess, a safer method is to start from the first item in the set and compare the rest against it.
Notice also that the two if statements are separate, not an if-else. A single city could be both the hottest and the coolest, if there were only one city in the set, and separate tests allow for that.
Checking whether a number is prime
A number is prime if it has no whole-number divisor except 1 and itself. Checking this needs a loop, because every possible divisor has to be tried, and it needs a break, because one divisor found is enough to settle the matter.
The variable is_prime starts as True and is only ever changed to False, so it works as a record of whether anything was found. Such a variable is often called a flag.
91 is a good number to test with, because it looks prime at a glance. The loop tries 2, 3, 4, 5, 6 and finds no divisor, then reaches 7 — and 7 × 13 = 91, so 91 % 7 is 0. The flag is lowered and break ends the loop at once. The remaining 83 divisors are never tried.
This program is correct but not efficient. To test a large number it checks every value up to number - 1, when in fact no divisor can be larger than the square root of the number. Replacing range(2, number) with a range that stops at the square root gives the same answers with far less work.
Building the Fibonacci series
In the Fibonacci series each number is the sum of the two before it, starting from 0 and 1: 0, 1, 1, 2, 3, 5, 8, and so on. The pattern turns up in the branching of plants and in several computing methods.
Here the count of numbers is not known in advance — only the point at which to stop — so this is work for a while loop.
The three lines at the end of the block do the work. next_number holds the new value while a and b are shifted along, because assigning to a first would destroy the value that next_number still needs.
The loop ends when a becomes 144, which is above the limit. Nothing counted the numbers — twelve of them appeared because that is how many fit under 100.
15.8 Summary
- Control flow is the order in which the statements of a program are carried out. A plain program runs in a straight line; conditions and loops let you bend that line.
- A condition is an expression whose value is only ever
TrueorFalse. Conditions are built from the comparison operators such as>,<,==and!=. - A block is a group of statements treated as one unit. Python marks a block by indentation, and the accepted style is four spaces. The line that introduces a block always ends with a colon.
- An
ifstatement runs its block once when the condition isTrueand skips it when the condition isFalse. - An
if-elsestatement gives two paths. Exactly one of the two blocks runs. - An
if-elif-elseladder gives many paths. Python tests the conditions from the top and runs the block belonging to the first one that isTrue, then leaves the statement. - A nested
ifis one conditional statement inside another. Use it when the inner question only makes sense after the outer one has been answered; use a ladder when the same fact is being split into ranges. - The
matchstatement, available from Python 3.10, compares one value against a list of cases.case _is the catch-all, matching anything the earlier cases did not. - Shorthand forms exist for small decisions: a single-statement
ifwritten on one line, and a conditional expression, which chooses between two values and must always include itselsepart. - A loop repeats a block of code. One run through the block is called an iteration.
- A
whileloop repeats as long as its condition staysTrue. It suits work whose length is not known in advance. Something inside the block must move the condition towardsFalse, or the loop never ends. - A
forloop runs its block once for each item of an iterable. Lists, tuples, strings, dictionaries and ranges are all iterables, and the loop variable takes a new value each time. range()produces a run of whole numbers. The starting number is included and the stopping number is not.- Looping over a dictionary gives its keys; looping over
.items()gives the key and the value together. - A nested loop is a loop inside a loop. The inner loop runs all the way through for every single iteration of the outer one, so the iterations multiply.
breakends a loop at once.continueabandons only the current iteration.passdoes nothing and simply fills a block that must not be left empty.breakandcontinuework only inside a loop, and in a nested loop they affect only the loop they are written in.passmay be used in any block.- Choose a
forloop when you could say in advance how many times the work must run, and awhileloop when you could not. - Wherever a program leaves data out of a calculation, the rule for leaving it out should be honest and recorded, because dropping values changes the answer.
15.9 Key Terms
- Block – a group of statements that belong together and are carried out as one unit.
- break statement – a statement that ends a loop at once and moves the program on to the line after the loop.
- Condition – an expression whose value is either
TrueorFalse. - Conditional expression – a one-line form that gives one of two values, chosen by a condition; also called the ternary operator.
- Conditional statement – a statement that tests a condition and carries out a block of code depending on the answer.
- continue statement – a statement that skips the rest of the current iteration and starts the next one, leaving the loop running.
- Control flow – the order in which the statements of a program are carried out.
- elif statement – short for “else if”; an extra condition hung under an
if, tested only when the conditions above it areFalse. - for loop – a loop that runs its block once for every item in a collection.
- if statement – a statement that runs a block of code once if its condition is
True, and skips it if the condition isFalse. - if-else statement – a statement that runs one block when its condition is
Trueand a different block when it isFalse. - if-elif-else ladder – a chain of conditions tested in order from the top, of which only the first
Trueone has its block run. - Indentation – the blank space at the start of a line, which in Python marks which lines belong to a block.
- Infinite loop – a loop whose stopping condition never becomes
False, so it runs until the program is forced to stop. - Iterable – an object able to hand over its items one at a time, such as a list, tuple, string, dictionary or range.
- Iteration – one single run through the block of a loop.
- Loop – a statement that repeats a block of code.
- Loop control statements – the statements
break,continueandpass, which change the ordinary flow of a loop from within its own block. - Loop variable – the variable in a
forloop that Python fills with the next item at the start of each iteration. - match statement – a statement that compares one value against a list of cases and runs the block belonging to the first case that matches.
- Nested loop – a loop written inside the block of another loop, so the inner loop runs completely for every iteration of the outer one.
- Nesting – writing one conditional statement inside the block of another.
- pass statement – a statement that does nothing, used as a placeholder where Python requires a block but no action is wanted.
- while loop – a loop that repeats its block for as long as its condition stays
True.
15.10 Objective Questions
Which keyword ends a loop immediately and moves the program on to the line after it?
- pass
- continue
- break
- elif
In Python, a block is marked by ______ rather than by brackets.
State whether the following is true or false: an
elsebranch may carry a condition of its own.Which numbers does
range(2, 9, 3)produce?- 2, 4, 6, 8
- 2, 5, 8
- 3, 6, 9
- 2, 5, 8, 11
Write the output of the following program.
for n in range(3):
if n == 1:
continue
print(n)The number given as the stopping value of
range()is ______ included in the numbers it produces.Match each keyword in the left column with its purpose in the right column.
Column A Column B a. whilei. walks through the items of a collection, one at a time b. forii. fills a block that must exist but needs no action c. passiii. catches every value that the earlier cases did not match d. case _iv. repeats a block for as long as a condition stays true
15.11 Concept Questions
What is a condition? Give one example of a condition written in Python.
Explain the difference between
breakandcontinue, and give one situation in which each is the right choice.Explain what
case _does in amatchstatement, and say which part of anif-elif-elseladder plays the same part.Why can a
whileloop run for ever while aforloop over a list cannot? Explain with reference to how each loop decides to carry on.When should a nested
ifbe used in place of anif-elif-elseladder? Support your answer with one example of your own.In a
whileloop, the line that increases the counter has been written below acontinuestatement. Explain what will happen when the program is run, and how it should be corrected.A list holds five distance readings taken by a robot. Write a program that prints each reading, together with the message
too closefor any reading below 25 cm.
15.12 Case-Based Questions
A school’s overhead tank has a level sensor. The maintenance rule is: below 30 per cent, switch the pump on; from 30 up to 80 per cent, leave the pump as it is; above 80 per cent, switch the pump off. Four readings taken during one day are shown below.
Time Level (per cent of full) 8 a.m. 18 11 a.m. 45 2 p.m. 72 5 p.m. 95 - Which conditional form suits this rule best, and why is a single
if-elsenot enough? - Write a program that stores one level in a variable and prints the correct instruction for it.
- A level of exactly 30 is recorded. State which instruction your program prints for it, and explain how you would change the program if the school wanted the opposite result.
- Which conditional form suits this rule best, and why is a single
A robot scans a corridor and stores its distance readings in a list. A student writes the following program to find the first point at which something blocks the way.
readings = [60, 48, 15, 33]
for reading in readings:
if reading < 20:
print("stop")
break
print(reading)- Write the output of the program as it stands.
- The team now wants the robot to ignore any negative reading, which means the sensor received no echo, and to carry on checking the rest of the list. Rewrite the loop to do this.
- Explain why part (a) needs
breakwhile part (b) needscontinue.