JJoeven

Curriculum/Python

Loops and Budgets

for and while repeat work. enumerate, zip, break, continue, any/all, and a hard step budget so the loop cannot run forever.

beginner20 min15 / 37

A loop does the same kind of work more than once. for walks every item in a list. while keeps going until a test is false.

A budget is a max number of steps. An agent is a loop: while the goal is not done and the budget remains, think, act, observe. Always count steps. Never write a loop with no stop. A model that never says “finish” must still hit max_steps.

A loop with a budget
ObserveThinkActBudget

While the goal is not done and steps remain, repeat. Budget is a hard stop.

A loop with a budget

If a live box hangs, you probably wrote while True without break, or you forgot to add to the counter. The site will eventually stop it. On a paid API, that hang is money.

for, range, enumerate, zip

for item in tools: sets item to each value, one at a time. A string, list, tuple, or dict keys can all be walked this way. for ch in "act": walks characters. for key in action: walks keys. Prefer for key, value in action.items(): when you need both.

range(n) is the numbers 0 through n - 1. range(1, 4) is 1, 2, 3. range is not a list. Wrap with list(range(3)) if you want to print it as a list. for i in range(3): is the usual retry loop: three tries, numbered 0, 1, 2. Use start=1 in enumerate when you want to print “step 1.”

enumerate gives you (index, item) together. zip walks two lists side by side and stops at the shorter one. Extra items on the longer list are ignored. If you need to notice a length mismatch, compare len first.

python
for name in [class="tok-s">"search", class="tok-s">"read", class="tok-s">"answer"]:
    print(name)

for i in range(3):
    print(i)  class="tok-c"># 0, 1, 2

for i, name in enumerate([class="tok-s">"search", class="tok-s">"read"], start=1):
    print(i, name)

for tool, query in zip([class="tok-s">"search", class="tok-s">"read"], [class="tok-s">"weather", class="tok-s">"file.txt"]):
    print(tool, query)

while, break, continue, and a budget

while test: repeats as long as the test is true. You must make the test false later. Forgetting to add to a counter is how you get an infinite loop (a loop that never ends).

break leaves the loop now. continue skips the rest of this round and starts the next one. Neither is evil. break on “goal done” is the agent’s success exit. continue on empty text skips a bad observation.

CodeTypical use
for msg in messagesWalk a log to build a prompt
for i in range(3)Retry a small number of times
enumerate(steps, start=1)Print step numbers
zip(names, args)Pair tool names with arguments
while used < max_stepsThe agent loop with a budget
any(flags) / all(flags)Did any fail? Did every field arrive?
sorted(names)Stable order for a print
breakGoal met, or a fatal error
continueSkip empty text

Never while True around a paid model call without a hard cap. Always count used against max_steps. A second cap on tokens or dollars is even better. The step cap is the one you can write today.

used += 1 should happen once per turn, at a known place. If you increment in two branches, you will double-count. If you increment after continue, you might skip counting. Put the increment at the top of the loop body.

any, all, and sorted

any(tests) is True if at least one item counts as yes. all(tests) is True only if every item counts as yes. Empty any([]) is False. Empty all([]) is True (no counterexamples). That empty case surprises people. Prefer not to call them on lists that might be empty unless you know the rule.

python
oks = [True, True, False]
print(any(oks))  class="tok-c"># True — at least one step worked
print(all(oks))  class="tok-c"># Falsenot every step worked

Use any for "did any tool fail?" Use all for "did every required field arrive?"

sorted(names) returns a new list in order. The old list does not change. Print a set of tool names with sorted(...) so the order is stable. list.sort() changes the list in place and returns None — the same trap as append.

else on a for or while

A loop can have else. That else runs only if the loop did not break.

python
for step in range(1, 4):
    if step == 99:
        print(class="tok-s">"found")
        break
else:
    print(class="tok-s">"never found")

That is how a budget stop can print "stop: budget" when finish never happened. If you break on finish, the else is skipped. The word else is confusing here. Think “if no break.” You will use this in the mini-agent lesson.

Common mistakes

  • while True with no break and no budget.
  • Forgetting used += 1.
  • continue before you record the step.
  • Expecting zip to error on different lengths.
  • for i in len(xs):len returns a number, which you cannot walk. Use range(len(xs)) or, better, enumerate.
  • Using for when the stop condition is “until done or budget,” which is a while.
Live PythonOpen full playgroundpython
Output
Run to execute this in your browser. Nothing is sent to a server.

Change the inner if used >= 4 to if used >= 99 so finish never happens. Then used should hit 8 and the while should stop on budget. That is the agent’s last seatbelt.

How agents use this

An agent is a while loop with a budget. Each turn adds one to used. for walks messages or tool names. enumerate numbers the trace so a person can say "step 7". any / all check a list of flags. break stops when the goal is done. A loop else runs only if you never broke — that is a clean "budget used up" message. Never let this loop run with no stop.

Retries are a small for i in range(3) around one tool, not a second infinite while. Nested unbounded loops are how a single user request becomes a thousand model calls. One outer while with max_steps. Inner loops over known lists.

Print used, goal_done, and the last observation every turn while you learn. That print is the trace. Later you append dicts instead of only printing. The loop does not change: test, act, record, test again.

Check your understanding

Which loop fits "run until the goal is true or steps hit 8"?