Lesson 2.2Lesson 2.2 · Control Flow & Collections
Loops - for and while
The engine of leverage: write an instruction once, apply it to every item, whether there are five or five thousand
Doing a task once and doing it a thousand times should cost you the same effort. The loop is the machine that makes that true.
In the very first lesson we called code leverage - the same instruction applied a thousand times for the cost of writing it once. The loop is the mechanism that delivers that promise. Everything else in scripting - reading files, cleaning data, generating geometry - is loops doing the heavy lifting.
There are two kinds. A `for` loop walks through a collection you already have - every room in a schedule, every file in a folder, every point in a grid - and does something to each. A `while` loop repeats as long as a condition stays true, useful when you do not know in advance how many times you will go round. Master these two shapes and you have the beating heart of automation.
for each thing in things: do the work. The loop is the leverage - write once, run N times for free.
The for loop: do this to every item
A for loop takes a collection and hands you its items one at a time, running the same indented block for each. The shape is simple and reads almost aloud:
rooms = ["living", "kitchen", "bath", "bed1"]
for room in rooms:
print(f"Designing the {room}")Read it as 'for each room in rooms, do the following'. On the first pass, the variable room holds "living"; on the next, "kitchen"; and so on until the list is exhausted. The name room is yours to choose - for r in rooms: works identically - but a meaningful name makes the loop self-documenting. The indented block, exactly like a conditional's block, is defined by its four-space indentation; when the indentation stops, the loop body is over.
The power shows the moment the collection grows. That same four lines process a list of four rooms or four thousand with no change at all - that is the leverage. And a for loop is not limited to lists: it will walk the characters of a string, the lines of a file, the rows of a spreadsheet, or the points of a grid. Anywhere you have 'a bunch of things to handle one by one', a for loop is the tool. You can also do real work inside it - accumulate a total, build a new list, print a report:
areas = [24.0, 12.5, 4.5, 15.0]
total = 0
for a in areas:
total = total + a
print(f"Total floor area: {total} sqm") # 56.0That running-total shape - a variable set before the loop and updated on every pass - is worth pausing on, because it is the simplest example of accumulation, one of the two things loops do. The first is to act on each item in turn: print it, rename it, draw it, tag it. The second is to build up a single answer from many items: a total, a count, a maximum, or a new list. Almost every loop you write is one or the other, or both at once, and naming which you need is half of designing the loop. In design work the accumulation is usually a schedule being assembled or a quantity being summed, which is why this pattern reappears the moment you start handling real project data.
range(): when you need to count, not just iterate
Sometimes you do not have a list to walk - you just want to repeat something a set number of times, or work with numbers in sequence. That is what range() is for. It generates a sequence of integers on demand:
for i in range(4):
print(i) # 0, 1, 2, 3Three things about range() surprise beginners, and all three are worth memorising. First, it starts at 0 by default, matching how Python numbers positions everywhere. Second, it stops before the number you give - range(4) yields 0, 1, 2, 3, which is four numbers but never reaches 4. Third, it can take a start and a step: range(2, 6) gives 2, 3, 4, 5, and range(0, 10, 2) gives 0, 2, 4, 6, 8. The 'stops before the end' rule feels odd at first but pays off - range(len(rooms)) gives exactly the valid index positions of a list, with no off-by-one to worry about.
In practice, when you want both the position and the item, reach for enumerate() rather than range(len(...)) - it is cleaner and it is what experienced Python programmers use:
rooms = ["living", "kitchen", "bath"]
for number, room in enumerate(rooms, start=1):
print(f"{number}. {room}") # 1. living / 2. kitchen / 3. bathThe while loop: repeat until something changes
A while loop repeats its block as long as a condition remains True. Use it when you do not know up front how many iterations you need - you are looping until some state changes:
budget = 100000
cost_per_unit = 18000
units = 0
while budget >= cost_per_unit:
budget = budget - cost_per_unit
units = units + 1
print(f"Afforded {units} units, {budget} left") # 5 units, 10000 leftThe loop checks the condition, runs the body, checks again, and stops the first time the condition is False. The critical discipline with while is that something inside the loop must eventually make the condition false - here, budget shrinks each pass until it can no longer cover a unit. Forget that, and you get an infinite loop: the program runs forever because the condition never changes. Every programmer writes one eventually; when your script hangs, an infinite loop is the first suspect, and Ctrl-C stops it. A good rule of thumb: prefer a for loop when you know the collection or the count in advance (which is most of the time in design work), and reach for while only when the number of repetitions genuinely depends on something that changes as you go.
for = known number of items. while = repeat until a condition flips. while needs an exit or it never stops.
Steering the loop: break and continue
Two keywords let you steer a loop from inside it. `break` jumps out immediately, abandoning the rest of the loop - useful when you have found what you were looking for and there is no point continuing. `continue` skips the rest of the current pass and jumps straight to the next item - useful for filtering out cases you want to ignore.
rooms = ["living", "", "kitchen", "corridor", "bath"]
for room in rooms:
if room == "":
continue # skip blanks, go to next room
if room == "corridor":
print("reached circulation, stopping")
break # stop the whole loop
print(f"Processing {room}")Here the empty string is skipped by continue, "living" and "kitchen" are processed normally, and hitting "corridor" triggers break, so "bath" is never reached. This pairing of a loop with an if inside it is one of the most common patterns in all of scripting: loop over everything, decide something about each item, and act or skip accordingly. It is exactly how you filter a schedule to just the wet rooms, find the first drawing that fails a check, or process files until you hit one that does not fit. Notice how naturally the conditionals from the previous lesson slot inside the loop - control flow is these pieces combined. Master the loop-with-an-if and you can express most of the everyday logic a designer needs to automate.
Nested loops, and the honest limits of leverage
Loops nest, and that is how a script covers a grid rather than a line. Put one for loop inside another and the inner loop runs completely for each pass of the outer one - which is exactly the logic of rows and columns, a structural grid, or a matrix of options:
for row in range(3):
for col in range(4):
print(f"position ({row}, {col})")That prints twelve positions - three rows, four columns each - and is the seed of generating a grid of columns, a run of facade panels, or a table of layout combinations. The rule to keep in mind is that the work multiplies: a loop over 100 items nested inside another over 100 items runs ten thousand times. Nesting is powerful but not free, so most everyday design tasks are happier with a single level; reach for a second only when your data is genuinely two-dimensional.
The other pattern worth cementing is building a result as you loop. You saw a running total above; the same shape builds a new list, a filtered subset, or a report. Start with an empty container before the loop, and add to it inside:
rooms = ["living", "kitchen", "bath", "bed1"]
areas = [24.0, 12.5, 4.5, 15.0]
large = []
for room, area in zip(rooms, areas):
if area >= 15:
large.append(room)
print(large) # ['living', 'bed1']This 'empty container, loop, conditionally add' pattern is the backbone of filtering and transforming data, and you will meet it again as the list comprehension in the next lesson and as the heart of the pandas work in Module 4. Notice how the pieces from this whole module click together here: a loop to iterate, zip to walk two lists in step, and a conditional to decide - control flow is not a bag of isolated tricks but these few moves combined. One honest caution about loops and leverage: a loop makes repetition free to write, not free to run. A script that loops over ten thousand files still takes real time, and a clumsy nested loop can be genuinely slow. That rarely matters at the scale of one project, but it is worth knowing that 'the computer will just do it' has limits - and that choosing the right collection, the subject of the next two lessons, is often what keeps a loop fast enough to feel instant.
It also helps to remember what a loop is not for. If you only ever do a thing once, a loop adds noise rather than value - just write the single line. If the collection is empty, the loop body simply never runs, which is usually what you want but occasionally hides a bug where the data failed to load. And if you find a loop growing long and tangled, that is often the moment to lift its body out into a function - the subject of the next module - so the loop reads as a clear sentence: 'for each room, do this named thing'. The loop is the engine, but like any engine it runs best when what it drives is well organised. Keep the body short, name your variables for what they hold, and a loop stays as readable a year later as the day you wrote it.
for loop
Run a block once for each item in a collection
The workhorse of leverage. Works over lists, strings, files, ranges - anything iterable. Same code for 5 items or 5,000.
while loop
Repeat a block as long as a condition stays True
For when the number of passes is not known ahead of time. Must contain something that eventually ends it, or it loops forever.
range()
Generate a sequence of integers to count or index
Starts at 0, stops BEFORE the end value. Takes optional start and step: range(0, 10, 2).
break / continue
Steer a loop: exit early, or skip to the next item
break stops the whole loop; continue skips the rest of this pass. Both usually sit inside an if.
enumerate()
Loop with both the index and the item at once
Cleaner than range(len(...)). Use start=1 for human-friendly numbering.
Workshop - a schedule summariser
Given a list of room areas, write a loop that totals them, counts how many exceed a threshold, and prints a tidy numbered report - the raw ingredients of an automatic area schedule. You will combine a for loop, an accumulator, a conditional and enumerate.
Python 3 in any editor or notebook. No libraries needed.
Goal: summarise a list of room areas with a loop Inputs: `areas = [24.0, 12.5, 4.5, 15.0, 9.0]` Time: ~25 minutes
- 1Start with the list
areas = [24.0, 12.5, 4.5, 15.0, 9.0]. Write aforloop that adds each value to a runningtotaland print the total after the loop. - 2Inside the same loop, keep a
countof how many rooms are 12 sqm or larger, using anifwith the comparison from the last lesson. Print the count. - 3Rewrite the report using
enumerate(areas, start=1)so each line prints like1. 24.0 sqm. Confirm the numbering starts at 1, not 0. - 4Add a
continuethat skips any area below 5 sqm (treat it as a cupboard, not a room) so it is left out of both the total and the report. - 5Now write a small
whileloop separately: starting from abudgetof 100000 and a cost of 18000 per room fit-out, count how many rooms you can afford. Make sure the budget decreases each pass so the loop ends. - 6Bonus: deliberately remove the line that decreases the budget, run it, watch it hang, and stop it with Ctrl-C - so you have met an infinite loop on purpose and know the fix.
You’ll walk away with
A script that prints the total area, a count of rooms over the threshold, and a numbered per-room report (cupboards skipped), plus a short while-loop that reports how many fit-outs a budget affords - with a one-line note on what caused and cured your infinite loop.
Three altitudes on the same idea
Read the band that fits you — or all three.
Loops are how one script touches an entire project. Iterate over every room in a schedule to total areas by department; walk every sheet in a set to stamp a revision; step through every element in an exported model to check for missing data. The tasks that eat a junior's afternoon - because they are the same small action repeated hundreds of times - are precisely what a for loop dispatches in seconds. When you later script Grasshopper or Dynamo, generating a grid of columns or a run of louvres is, at heart, a loop.
Every list you maintain is a loop waiting to happen. An FF&E schedule, a room-by-room finishes matrix, a batch of product images to rename - loop over the list and apply the same operation to each line: sum the costs, flag the over-budget items, format the labels. What feels like tedious line-by-line work is a single loop that runs the moment the data changes. Combined with the conditionals from the last lesson, a loop lets you re-check and re-price an entire scheme automatically.
If you learn one construct deeply this module, make it the loop. Nearly every algorithm and every data operation you will ever write is a loop at its core, and the loop-with-an-if-inside is the pattern behind filtering, searching, counting and transforming. Practise it now on lists you understand - rooms, areas, materials - and the leap to processing spreadsheets with pandas, generating geometry, or running a simulation later becomes a change of subject, not a change of skill.
“You loop by keeping a counter variable and manually incrementing it, like `i = i + 1`, the way older languages do.”
for loop iterates directly over the items of a collection - for room in rooms: hands you each room, no counter required - which is cleaner and cannot run off the end of the list. When you genuinely need the position too, use enumerate(rooms) to get index and item together, not a hand-maintained counter. Manual counters belong to the while loop, where you deliberately change a value each pass until a condition flips; even then, forgetting to update it gives you an infinite loop. The Python habit to build is: iterate over things, not over index numbers, unless the index is truly what you need.Do it yourself
Predict the output before you run each one.
- 1How many numbers does
range(4)produce, and what are they? - 2What is the difference between
breakandcontinueinside a loop? - 3When would you choose a
whileloop over aforloop? - 4What is an infinite loop, and what is the usual cause with a
while? - 5Rewrite
for i in range(len(rooms)): print(rooms[i])usingenumerateinstead.
The one line to carry out
Peer-reviewed journals & authoritative standards
- 01For loop — Wikipedia, 2026.
- 02While loop — Wikipedia, 2026.
- 03Control flow — Wikipedia, 2026.
- 04The Python Tutorial — Python Software Foundation, 2026.
for loop walks a collection item by item, running the same block each time - the same code handles five items or five thousand. range() counts for you (from 0, stopping before the end), and enumerate() gives index and item together. A while loop repeats while a condition holds and needs something inside it to eventually stop. break exits a loop early; continue skips to the next item; and pairing a loop with a conditional is the core of everyday automation.Loops are only as useful as the collections they run over. So far we have used lists in passing - next we look at them properly: how to build, index, slice and grow the list, the workhorse collection that most of your loops will iterate.
The author
Amogh N P
Architect, interior designer, and creative polymath. Studio Matrx began in his notebooks — his vision of design made honest, useful, and open to everyone. Its Academy is written and taught in his memory, and free, forever.
More about Amogh →