Conditions and loops
A condition is a yes or no question a program asks itself at a fork, and a loop is work that repeats for as long as some condition holds. Almost every program you will ever write is a combination of those two, and the hardest bugs land exactly where they meet.
- Lesson 6 of 14
- Beginner
- Free, no signup
One full turn of a loop, and the only way out
- 1 Test the condition
- 2 Run the body
- 3 Change one thing
- 4 Go back to the top
The only way out of this ring is for the condition at the top to become false. A loop whose body changes nothing that the condition reads never leaves it.
Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.
What is a condition, and what does a program lack without one?
A condition is a question with only two answers, yes or no, and the program takes one of two routes depending on which it gets. A program with no conditions is a list of instructions that always runs the same way from top to bottom; with the first condition, that list turns into something that reacts to a situation.
age = 17
if age >= 18:
print("allowed")
else:
print("denied")The second line is the question, the third is the yes route, the fifth is the no route. The else is optional: leave it out and nothing happens when the answer is no, the program simply walks past the condition without a word. That silence matters later.
Two classic mistakes are waiting here. The first is confusing one equals sign with two: = means assign, == means compare. Python is kind about this and raises a syntax error if you put one equals sign inside a condition, but the languages this site is built with, PHP and JavaScript, raise nothing at all: if ($x = 5) assigns and is then always true, so your condition effectively does not exist and nobody says a word.
The second mistake is order, and it gets discussed far less. When you chain several conditions, the first one that is true wins and the rest are never even evaluated. So if you put the general condition above the specific one, the specific one never runs and you spend hours hunting a bug that is not there. The code is correct; only its order is wrong.
One question, two routes, and the code that is never tested
Does the condition hold?
The if body runs
- The other branches are never evaluated
- The program continues after the body
The else body runs, if you wrote one
- Without an else nothing happens and nothing is reported
- That silence is the hardest case to find
When several conditions are chained, the first true one wins and the rest are never evaluated at all. Do not put the general condition above the specific one.
What is a loop, and what does every loop need?
A loop means: do this work more than once instead of once. Its value is in the count. Writing three lines for three files is no great feat, but those same three lines for thirty thousand files are only possible with a loop, and more importantly your code becomes independent of the number.
There are two main shapes. The first walks a collection and runs once per member:
names = ["ali", "sara", "reza"]
for name in names:
print(name)The second turns for as long as a condition holds, and how many times is not known in advance:
size = 4096
step = 0
units = ["B", "KB", "MB", "GB"]
while size >= 1024 and step < len(units) - 1:
size = size / 1024
step = step + 1Every loop, whatever its shape, needs three things, and breaks if one is missing: something to walk or a condition to test, something that changes on each turn, and a way to end. In the second example size and step are the things that change; delete the line size = size / 1024 and the condition stays true forever.
One detail tutorials usually skip: the second half of that condition, step < len(units) - 1, has nothing to do with size. All it does is stop the loop walking off the end of the unit list. That loop lives in this site's own dashboard code, and that second half is the only thing standing between it and a real error.
Which loop goes where? A real count from this site's code
Most tutorials start with the counting loop, the one where a counter climbs from zero to some number. In real code it is the least used shape, and rather than guess we counted this site's theme.
Across 193 PHP files in the theme there are 560 collection loops, 21 counting loops and 13 conditional loops. So the shape you learn first accounts for under four percent of the loops in this codebase.
The reason is plain: you almost never want the member's number, you want the member. When you write "for each file in this folder", the file's index is no use to you, and keeping a counter is just one more place to be wrong. The 21 that remain are exactly where a number really is needed: drawing five review stars, building the columns of a table, walking backwards through the months of a chart.
We looked at those 13 conditional loops too, since the list was short. Seven are the main WordPress loop, which turns while posts remain. Three make a duplicate identifier unique: while this name has already been used, add a number to the end of it. The last three are places where the count genuinely is unknown: reading from a socket to the end of a response, converting bytes to a larger unit, and generating a username until it is not taken.
The rule that falls out of this count is more useful than any definition: if you know what you are walking over, write a collection loop. If you do not know when it ends, write a conditional loop. And if you genuinely need the number itself, then a counting loop, which in practice comes up rarely.
Collection loop or conditional loop?
Collection loop
- When you already know what you are walking over
- The collection itself decides how many turns
- An endless loop is nearly impossible
- Runs zero times on an empty collection
- In this site's theme: 560 of them
Conditional loop
- When you do not know how many turns it takes
- You have to change something yourself for it to end
- Reading a response to its end, or making a unique name
- Every endless loop comes from this family
- In this site's theme: 13 of them
Neither of these is better than the other; they are for two different situations. Our count on this codebase shows the first column comes up far more often in practice, not that the second is wrong.
What does an endless loop look like on a real server?
An endless loop is a loop whose stopping condition never becomes false. It has two common shapes and both share one root: whatever the condition reads is not changed inside the body.
The first shape is forgetting that change altogether: the condition says turn while the counter is under ten, and nobody inside the body ever increases the counter. The second is changing it in the wrong direction, which is worse because the code looks full of movement: the counter goes down while the condition is waiting for it to go up.
Now the question no tutorial answers: what actually happens if this lands on a live site? The browser does not wait forever. On this server there is a setting called request_terminate_timeout and its value is 180 seconds. Any request still running after three minutes has its process killed.
And killed is the precise word here, not a metaphor. This is not a PHP error you can catch; the process is closed from outside. The consequence is that your ending code does not run: if the loop was halfway through writing a file, the file stays half written, and if it had taken a lock, the lock is not released. What the visitor sees is a generic server error page that says nothing about your loop.
So the skill to take away is this: you do not find an endless loop from an error message, because there is no error message. You find it from the clock. A page that always fails at almost exactly that same three minute mark is nearly always a loop, or a wait that never ends.
Conditions inside loops: break, continue and the off-by-one
The real home of these two ideas is side by side: a loop that makes one decision per member. The five line program in the first lesson of this track was exactly that, a loop over files with a condition on size.
Two words change the work here. break abandons the whole loop and leaves; continue abandons only this turn and moves to the next member. The first is for when you have found your answer, the second for when this member is of no use to you.
The surprise everyone meets once: if one loop sits inside another, break only breaks the inner one, not both. The program leaves the inner loop and quietly starts the next turn of the outer one. The code raises no objection and you believe you got out.
Another mistake has a name of its own, the off-by-one: the loop runs one time more or one time less than you expected. Its main source is that ranges are usually closed at the start and open at the end. In Python range(1, 10) gives you one through nine and not ten. That decision is not strange and it has a reason, but memorising it does not work; what works is writing one out and counting the output.
And the last case, the quietest of all: a loop over an empty collection. It runs zero times, raises no error and prints nothing. A program that did no work and made no complaint is always the first thing to check, not the last.
How do you read a loop you did not write?
This skill matters more today than writing loops, because code is read far more than it is written and a large part of that code was not written by you. Our method is four questions, and their order matters.
One: what is it walking over, and can that thing be empty? If it can, the loop runs zero times, and that is usually the case nobody tested.
Two: what changes on each turn? If your answer is nothing, either the loop is endless or the loop is pointless.
Three: what stops it, and could that never happen? Look for break statements here too, because an early exit is not always written at the top of the code.
Four: what is true after the last turn? What values do the variables built inside the loop hold afterwards, and is anyone relying on them?
Try those four on the unit conversion loop above: it walks no collection, so emptiness does not apply; two things change; the condition has two halves and one of them is only a guard; and after the last turn step holds the index of the correct unit, which is exactly what the next line uses. Four answers, and now you understand the loop without running it.
The fast path, with AI
What genuinely changed in this topic is not writing loops; writing loops was never the hard part. What changed is that ten loops a day now reach you that you did not write, and you have thirty seconds to work out where each of them breaks. So the recipe below does not ask the model for code; it asks it to answer the four questions above about code you already have. A frontier model suits this better than a fast cheap one, because it is judgment work; our current pick among coding models sits in the AI section of this site.
- Copy the whole loop with a few lines above and below it, not just the loop. The value the condition reads is usually built outside the loop, and without it the model is guessing.
- Send the recipe below and say plainly that it must not rewrite the code. Allow a rewrite and you get a new version instead of an explanation, and the first thing lost is the very case you wanted to understand.
- Take the empty case answer seriously. In our experience that is what this recipe surfaces most: a loop that turns zero times on an empty list, with nothing in the code after it allowing for that.
- Before accepting the answer, run the loop yourself with an empty input and a single member input. Those two cases are the cheapest test that exists, and most loop bugs show up right there.
Copy-ready recipe
This code is not mine and I want to understand it, not change it.
{paste the code here, with a few lines above and below the loop}
Do not rewrite the code. Answer only these four questions, two sentences each:
1. What does this loop walk over, and can that thing be empty? What happens if it is?
2. Which variables change on each turn, exactly?
3. What stops the loop, and is there a case where it never stops? Include any early exits.
4. After the last turn, what value does each variable built inside the loop hold?
At the end, say which of those four answers you cannot be sure of from the code alone, and what you would need in order to know.
Before you trust the output: The last paragraph of the recipe is its most important one, and removing it breaks the whole thing. A model describes what it cannot see in exactly the same confident tone, and what it cannot see here is usually the place where the collection is built. So any answer about emptiness or termination is a hypothesis rather than a fact until you have run it once with an empty input yourself.
AI in this kind of work
Loops and conditions are precisely the kind of code language models write flawlessly. Thousands of examples of these exact structures sat in their training data, and the result is that producing them no longer counts as a skill. So what is left for you is reading: working out where this loop breaks, which case this condition forgot, and whether this code does what you think on an empty input. Our position is to keep the model in the role of explainer rather than author for this topic; code you did not write and cannot explain line by line is not your code.
Tools that actually help
- Claude Good at taking a chunk of code and describing its behaviour, and when you say plainly not to rewrite it, it improvises a new version less often. Iran is on neither of Anthropic's two supported-countries lists; we read that on Anthropic's own page rather than measuring it.
- Claude Code A command line tool, and its edge for this job is one thing: instead of a snippet it sees the repository, so it can go and look at where the collection your loop walks actually came from. It installs free but does not run without a Claude subscription or an Anthropic Console account, and Iran is not on the supported-countries list.
- Gemini It has a separate study mode called Guided Learning that asks questions instead of handing over answers, which suits those four loop reading questions well. Google's own page says the Gemini web app runs in over 230 countries and territories, and Iran is not on that list.
Where it backfires
The specific risk in this topic is this: a model talks about a loop with complete confidence while never having seen the collection that loop walks. If that collection comes from a database query or a network request and you copied only the loop itself, the sentence "this loop is safe" is a guess written to look like a fact. Anthropic itself calls this hallucination in its own documentation and explains how to reduce it, which means the vendor treats it as a real weakness rather than a rumour.
The second risk is more practical: when you ask a model to make a slow loop faster, the version it returns often behaves differently at the edges, especially on an empty input and on a single member input. So test every rewrite with those two inputs, not with the ordinary input that always works. For how each of these tools can be paid for from Iran, see the buying guide, and for our current pick among coding models, the best AI for coding.
Sources: Anthropic: reduce hallucinations Anthropic: supported countries Claude Code: overview and install Google: where the Gemini web app is available
Where this advice stops
The syntax on this page is Python. The shape of a condition and a loop exists in every language, but the writing differs and copying these lines straight into PHP or JavaScript will not work. Second, this lesson deliberately leaves out recursion, generators and comprehensions; they are other routes to the same work and they only start to mean something once these two basic structures have settled. Third, the thing you were probably waiting for: which loop is faster. We give no number about speed, because at the sizes a beginner works with the difference is not measurable and we have not measured it on this server either. A loop that is correct and readable beats a loop that might be faster.
From our own work
On the day this lesson was checked, instead of guessing, we opened this server's own PHP configuration file. In /www/server/php/85/etc/php-fpm.conf there is a line reading request_terminate_timeout = 180. Any request still running after 180 seconds has its process closed from outside. PHP's official manual says the same: this setting is the timeout after which the worker process is killed. The consequence that matters for this lesson, and that no loop tutorial writes down, is that because the process is killed rather than raising an error, your ending code does not run. A loop halfway through writing a file leaves that file half written. We ran the same kind of count over the site's theme and, across 193 PHP files, reached 560 collection loops, 21 counting loops and 13 conditional loops; all three numbers can be reproduced with one plain search over that folder.
Real follow-up questions
What is the difference between for and while in practice?
In practice the difference is who decides how many turns there are. In a collection loop the collection decides and you do nothing; in a conditional loop you have to change something yourself or it never ends. That is also why nearly every endless loop is of the second kind.
When should I use break and continue?
When you have found your answer and continuing the loop serves no purpose, use break. When this particular member is of no use to you but the others might be, use continue. One warning: with nested loops, break only breaks the inner one and the program quietly starts the next turn of the outer one.
Why does my loop run one time more or less than I expected?
This is called the off-by-one, and its main source is that ranges are usually closed at the start and open at the end: in Python range(1, 10) gives you one through nine. The fix is not memorising it; print that range once and count its members, and after that you will not get it wrong.