Conditions and loops
reading the flow of control
What it is
Control flow is the order in which lines execute. Top to bottom by default, but conditions and loops change that: some lines are skipped, some are repeated.
To read code like this you need to be able to answer one question: on what data does this line execute? The rest follows.
What it looks like in code
orders = [
{"id": 1, "status": "paid", "total": 250},
{"id": 2, "status": "pending", "total": 0},
{"id": 3, "status": "paid", "total": 90},
]
total = 0
for order in orders:
if order["status"] != "paid":
continue
if order["total"] <= 0:
print(f"order {order['id']}: paid, but the amount is zero")
continue
total += order["total"]
print("total:", total)Output:
total: 340How to read it
Indentation is scope. Everything shifted right of a for or an if
belongs to it. In Python indentation is not formatting but syntax: move a line
and you change the meaning of the program.
continue means "skip the rest and take the next item". The two of them
in the example are filters: unpaid orders and zero-value orders never reach
the addition.
break means "leave the loop entirely". Confusing the two is a common
reading error: continue skips one step, break ends the iteration.
A loop's else is a rare construct, but it does turn up. It runs if the
loop finished without a break.
List comprehensions
The same meaning fits on one line:
paid = [o["total"] for o in orders if o["status"] == "paid"]
print(sum(paid)) # 340It reads, in meaning, right to left: take o from orders where the status
is paid, and collect their o["total"]. The AI writes these readily —
they are short, but with two or three conditions they become unreadable.
The ternary expression
status = "paid" if order["total"] > 0 else "pending"Reads as: status equals "paid" if the condition holds, otherwise
"pending". The same construct in JavaScript and Dart is written differently:
const status = order.total > 0 ? "paid" : "pending";The ? before the first option, the : before the second — same thing, other
syntax.
What to tell the AI
On what data does line 14 execute? Give a concrete example
of input that gets us there.Can this loop run zero times? On what data?The second question matters more than it looks. A loop over an empty list simply does nothing — silently, with no error. If the code below expects the variable to have accumulated something, it gets zero or emptiness.
What to look for
Deep nesting. Three or more levels of if inside for inside if is
hard to read and easy to break. A sign that some conditions could become an
early continue or move into a function of their own.
A loop that might not run. An empty list, an empty API response — and the whole block is skipped. Check that the code below accounts for that.
Modifying a list while iterating it. Removing items from the same list the
for is walking gives you skipped items. It looks harmless and works
incorrectly.
A condition that is always true or always false. This happens after edits:
if status != "paid" or status != "pending" is true for every value.
Substituting any value is enough to spot it.
Cheat sheet
Indentation in Python is syntax, not formatting.
continueskips a step,breakleaves the loop.A comprehension reads like a loop: take, filter, collect.
The main question: on what data does this line execute?
The second question: can the loop run zero times?
Don't modify a list while you are looping over it.