Python flow control: if, for, while, break, continue and nested loops
Advertisement
By default Python runs your statements from the first line to the last. Flow control is how you change that: choosing between paths with conditions, repeating work with loops, and jumping out of a loop early. Almost every real program is built from these few pieces. This post covers conditional statements, the two loops, the statements that transfer control, and nested loops, with output from real runs on Python 3.9.
Conditional statements
if, if-else and if-elif-else
marks = 72
if marks >= 60:
print("first division")
elif marks >= 45:
print("second division")
else:
print("fail")
This printed first division. Python checks the conditions from top to bottom and runs only the first block that is true; the rest are skipped. elif and else are optional, and else has no condition. The colon after each condition and the indentation (four spaces is the convention) are required, because indentation is how Python knows which lines belong to the block. Mixing tabs and spaces causes an IndentationError.
A common beginner mistake is to write separate if statements where elif was meant:
n = 85
if n >= 80: print("A")
if n >= 60: print("B") # also runs, because it is a separate if
This printed both A and B. With elif the second test would be skipped.
What counts as true
A condition does not have to be a comparison. Python treats these as false: False, None, 0, 0.0, "", [], (), {}, set() and range(0). Nearly everything else is true.
for value in [0, 1, "", "a", [], [0], None]:
print(repr(value), bool(value))
0 False
1 True
'' False
'a' True
[] False
[0] True
None False
So you can write if items: instead of if len(items) > 0:. Combine conditions with and, or and not, and use chained comparisons such as if 18 <= age < 60:. The operators post explains short-circuit evaluation.
One-line forms
age = 20
status = "adult" if age >= 18 else "minor" # conditional expression
print(status) # adult
Use the one-line form only for simple choices. Nested versions are hard to read.
Nested conditions
An if can sit inside another if. Keep nesting shallow; a guard clause often flattens it:
def discount(is_member, total):
if not is_member:
return 0
if total >= 1000:
return 10
return 5
print(discount(True, 1500), discount(True, 200), discount(False, 5000)) # 10 5 0
Python 3.10 added a match statement for matching a value against several patterns. It is not needed for the examples here, and works only on 3.10 and newer.
Iterative statements: loops
The for loop
A for loop visits each item of a sequence (a list, string, tuple, dictionary, range, file) in turn.
for ch in "abc":
print(ch, end=" ") # a b c
print()
for fruit in ["apple", "banana"]:
print(fruit.upper()) # APPLE then BANANA
To repeat something a set number of times, use range():
print(list(range(5)), list(range(2, 8)), list(range(10, 0, -3)))
# [0, 1, 2, 3, 4] [2, 3, 4, 5, 6, 7] [10, 7, 4, 1]
range(stop), range(start, stop) and range(start, stop, step) never include stop. A range is lazy: range(1_000_000_000) takes almost no memory. When you need both the position and the item, use enumerate:
for i, name in enumerate(["Asha", "Ravi"], start=1):
print(i, name) # 1 Asha then 2 Ravi
Looping over a dictionary gives its keys; use .items() for pairs:
prices = {"tea": 20, "coffee": 30}
for item, price in prices.items():
print(item, price) # tea 20 then coffee 30
The while loop
A while loop repeats as long as its condition is true. Use it when you do not know in advance how many times to repeat.
n = 5
total = 0
while n > 0:
total += n
n -= 1
print(total) # 15
You must change something inside the loop that moves the condition towards false. Forgetting n -= 1 would make an infinite loop.
Infinite loops on purpose
Sometimes a loop should run until something specific happens. The usual form is while True with a break:
attempts = 0
while True:
attempts += 1
if attempts * attempts > 50:
break
print(attempts) # 8
Menus, servers, games and "ask until valid" input all work this way. If a program hangs because of an accidental infinite loop, press Ctrl+C to stop it.
Transfer statements
Three statements change how a loop behaves from the inside.
break
break leaves the nearest loop immediately.
for n in range(10):
if n == 4:
break
print(n, end=" ") # 0 1 2 3
print()
continue
continue skips the rest of the current round and jumps to the next one.
for n in range(8):
if n % 2 == 0:
continue
print(n, end=" ") # 1 3 5 7
print()
pass
pass does nothing. It is a placeholder where Python requires a statement but you have nothing to write yet:
def placeholder():
pass
for _ in range(3):
pass
print(placeholder()) # None
else on a loop
A for or while loop may have an else block. It runs when the loop finishes normally, that is, without hitting break. It is the clean way to write a search:
for n in [15, 13]:
for d in range(2, n):
if n % d == 0:
print(n, "is divisible by", d)
break
else:
print(n, "is prime")
15 is divisible by 3
13 is prime
Many programmers find loop else surprising at first. Read it as "no break happened".
Nested loops
A loop inside a loop runs its full cycle for each round of the outer one. This is how you handle tables, grids and patterns.
for i in range(1, 4):
for j in range(1, 4):
print(i * j, end="\t")
print()
1 2 3
2 4 6
3 6 9
A star triangle uses the outer loop for rows and the inner loop for the columns of each row:
for row in range(1, 5):
print(" " * (4 - row) + "*" * (2 * row - 1))
*
***
*****
*******
break and continue affect only the innermost loop. To leave both loops at once, put them in a function and return, or use a flag:
def find_pair(target):
for a in range(1, 10):
for b in range(a, 10):
if a * b == target:
return a, b
return None
print(find_pair(24), find_pair(97)) # (3, 8) None
Putting it together
Here is a small program that mixes everything: it sums the numbers 1 to 20 that are not multiples of 3 and stops if the running total passes 100.
total = 0
for n in range(1, 21):
if n % 3 == 0:
continue
total += n
if total > 100:
print("stopped at", n)
break
else:
print("never passed 100")
print(total)
It printed stopped at 17 and then 108, showing a loop with continue, break and else working together.
Choosing between for and while
Use for whenever you are going through the items of something or repeating a known number of times. Use while when the stopping point depends on something that changes while the loop runs, such as user input, a search converging or a retry counter. If you write i = 0 ... while i < len(x): ... i += 1, a for loop would be shorter and safer.
Common mistakes
- Using
=instead of==in a condition (Python reports aSyntaxError). - Writing several
ifstatements whenelifwas meant. - Wrong indentation, or mixing tabs and spaces.
- An infinite
whileloop because the variable never changes. - Changing a list while looping over it; loop over a copy or build a new list.
- Expecting
breakto leave all nested loops. - Off-by-one errors with
range: remember that the end is excluded.
Practice
Write a program that prints the numbers from 1 to 50, but Fizz for multiples of 3, Buzz for multiples of 5 and FizzBuzz for both. Then print all prime numbers below 50 with a nested loop and loop else. Finally, ask the user to guess a number between 1 and 20 and keep asking until the guess is right, counting the attempts.
Continue
Use flow control together with input and output, wrap repeated logic in functions and handle bad input with exception handling. The language fundamentals post covers the basic types, and the Python video course has step-by-step lessons.