Making Decisions & Loops
Branch with if, loop over anything with for, count with range(), and learn Python's unusual else clause on loops.
You will learn
if/elif/else, truthiness, and the one-line conditional expression.- How Python's
forloop walks over items, not indexes. - How
range()works (start, stop, step) and why it is "lazy". break,continue, and theelseclause on loops.pass, the statement that does nothing.
if statements
An if statement runs a block only when a condition is true. elif ("else if") checks another condition, and else catches everything left over. Python checks them top to bottom and runs only the first matching block.
- Each condition line ends with a colon
:. - No parentheses are needed around the condition: write
if amount < 0:, notif (amount < 0) {. - Logical operators are words:
and,or,not(not&&,||,!).
β Java / π¨ JS: Python has no switch. A chain of elif is the usual replacement, and for matching on shapes of data there is match (Chapter 4). There is no ternary ?: either; see the conditional expression below.
Truthiness
A condition does not have to be True or False. Python asks the object "are you true-ish?" These values count as false; everything else is true:
False,None- zero:
0,0.0 - empty containers:
"",[],(),{},set(),range(0)
β Wordy
β Pythonic
β οΈ Pitfall: unlike JS, the string "0" and the string "False" are true: they are non-empty strings. And [0] is true because the list has one item.
The conditional expression (Python's ternary)
When you just need to pick one of two values, use X if condition else Y. It reads like English.
for statements
Python's for is a for-each loop. It walks over the items of any iterable: anything that can hand out its items one at a time, such as lists, strings and ranges. There is no for (i = 0; i < n; i++) form.
β Java: like for (String w : words). π¨ JS: like for (const w of words). Python's in is JS's of, not JS's in.
Don't change a collection while you loop over it
Changing a list (or dict) while looping over it confuses the loop: items can be skipped. Loop over a copy, or build a new collection.
β Skips items
β Build a new list
(Chapter 6 shows a one-line way to do this: [n for n in nums if n != 2].)
The range() function
When you need a sequence of numbers, use range(). Like slicing, it includes the start and excludes the stop.
| Call | Numbers produced |
|---|---|
range(5) | 0, 1, 2, 3, 4 |
range(5, 10) | 5, 6, 7, 8, 9 |
range(0, 10, 3) | 0, 3, 6, 9 |
range(-10, -100, -30) | -10, -40, -70 |
range(10, 0, -2) | 10, 8, 6, 4, 2 |
range(5, 2) | (nothing: start is already past the stop) |
range(10) does not build a list of ten numbers. It produces each number on demand ("lazily"), so range(1_000_000_000) uses almost no memory. Functions like list() and sum() accept any iterable and pull the numbers out.
Looping with indexes
If you need the index too, you can combine range() and len(), but enumerate() (Chapter 7) is the usual way:
β Works, but un-Pythonic
β Pythonic
break and continue
breakleaves the innermostfororwhileloop immediately.continueskips the rest of this pass and jumps to the next item.
A common pattern is an "infinite" loop that exits with break:
else clauses on loops
This feature surprises everyone coming from Java or JS. A for or while loop can have an else block. It runs when the loop finishes without hitting break.
Think of it as "no break". It is perfect for searches: the else means "I looked everywhere and didn't find it".
Look carefully: the else is lined up with the inner for, not with the if. That is what makes it a loop-else.
| How the loop ended | Does else run? |
|---|---|
| Ran through every item | β yes |
| Iterable was empty (zero passes) | β yes |
break | β no |
return or an exception | β no |
continue (any number of times) | β yes (continue doesn't end the loop) |
β Java-style flag
β for β¦ else
π‘ Tip: for a simple membership test, if "fun" not in categories: is even shorter. Save forβ¦else for searches that also do work along the way.
pass statements
pass does nothing. You use it where Python's grammar needs a statement but you have nothing to write yet, for example an empty function or class while sketching.
You can also write ... (the Ellipsis object) as a placeholder body. Many people use it in stubs.
More examples
1. Categorise expenses
2. First expense over budget
3. Ask until valid (with a stand-in for input())
("-5".isdigit() is False because - is not a digit.)
4. FizzBuzz, the Python way
5. A multiplication table with nested loops
Recap
if / elif / elseruns the first matching branch. Conditions use truthiness: empty and zero values are false.a if cond else bis Python's ternary.for x in iterablewalks over items. Useenumerate()when you need indexes, and don't change a collection while looping over it.range(start, stop, step)excludes the stop and is lazy.breakexits a loop, andcontinueskips to the next pass. A loop'selseruns only if nobreakhappened.passis a do-nothing placeholder.
Exercises
Exercise 1 π’ easy predict the output
What is list(range(2, 12, 3))?
Show solution
[2, 5, 8, 11]. It starts at 2 and adds 3 each time. 14 would be past the stop (12), and the stop itself is never included.
Exercise 2 π’ easy fix the bug
This Java-style code has three syntax errors. Fix them.
Show solution
Python uses a colon plus indentation instead of braces, and elif instead of else if.
Exercise 3 π’ easy predict the output
Which of these print yes? if "0":, if 0:, if []:, if [0]:, if None:, if " ":
Show solution
"0", [0] and " " are true: they are non-empty. 0, [] and None are false.
Exercise 4 π’ easy build it
Print the even numbers from 10 down to 0 (10, 8, β¦, 0) using one range() call.
Show solution
The stop must be -1 so that 0 is included, because the stop is excluded.
Exercise 5 π‘ medium predict the output
What does this print?
Show solution
all odd. The loop never hits break, so the loop's else runs.
Exercise 6 π‘ medium refactor it
Rewrite this using a conditional expression on one line.
Show solution
The conditional expression is an expression (it has a value), so it can sit on the right side of =.
Exercise 7 π‘ medium fix the bug
This should remove every negative number, but -2 survives. Why? Fix it.
Show solution
Removing -1 shifts -2 into index 1, but the loop moves on to index 2, so -2 is never checked. Never shrink a list while looping over it.
Exercise 8 π‘ medium build it Β· playground
Create playground/budget_check.py. Given expenses = [12, 30, 75, 8, 120] and budget = 100, add the expenses one by one and stop as soon as the running total goes over the budget. Print which expense pushed it over. If none did, print Within budget.
Show solution
break stops at the first overflow, and the else handles the "never happened" case without a flag variable.
Exercise 9 π΄ hard predict the output
How many lines does this print, and what is the last one?
Show solution
Three lines: 1 0, 2 0, 2 1. The last one is 2 1. When i == 0, j = 0 is skipped and j = 1 > 0 breaks out. break only leaves the inner loop, so the outer loop carries on.
Exercise 10 π΄ hard explain why
Does the else run here? Why?
Show solution
Yes, it prints else ran. The loop body never runs, so break never runs either. The else means "the loop wasn't broken out of", and that includes the empty case.
Exercise 11 π΄ hard mini-project Β· playground
Create playground/primes.py that prints every prime number below 50 on one line, separated by spaces. Use nested loops, break and a loop else. Bonus: only test divisors up to the square root (x * x <= n).
Show solution
whileβ¦else works just like forβ¦else. If n has a factor bigger than βn, it also has one smaller than βn, so checking up to βn is enough.