TechByteByByte

Python Control Flow

Learn how Python makes decisions and repeats work using if/elif/else, for loops, while loops, and loop control statements, with AI examples like filtering documents and retry logic.

#Python#Control Flow#Loops#Conditionals#AI#Python for AI

The problem: Code that only runs from top to bottom cannot react to a different input. An AI application must ask “is this response valid?”, repeat “process every document,” and stop when “three retries have failed.”

What you will learn: Control flow chooses which instruction runs next. You will make decisions with if, repeat work with loops, and stop or skip work with break and continue. Python is not forming human judgment here; it is following the exact conditions you wrote.


1. if / elif / else

Control flow changes which instruction runs next. Without it, every program would follow one fixed path regardless of its input.

input arrives

check a condition ── true ─→ run path A

    false

run path B

continue with shared code

A condition does not understand a situation like a person. It is an expression that Python evaluates as truthy or falsy. Your code defines what each result should mean.

Control flow changes which instruction runs next. Without it, every program would follow one fixed path regardless of its input.

input arrives

check a condition ── true ─→ run path A

    false

run path B

continue with shared code

A condition does not “understand” the situation like a person. It is an expression that Python evaluates to a truthy or falsy value. Your code—not Python—defines what each result should mean.

The Basic Decision

A way to run different code depending on whether a condition is True or False.

Why Programs Need Branches

Programs need to react differently to different situations — an AI app should behave differently when a response is empty than when it’s valid.

Picture It as a Fork

Think of if as a fork in the road — the program takes one path or the other, never both.

A Familiar Example

A bouncer at a club: “If you’re on the list, let them in. Else if they’re with someone on the list, let them in. Else, turn them away.”

Syntax

if condition:
    # runs if condition is True
elif another_condition:
    # runs if the first was False but this is True
else:
    # runs if nothing above was True

Example

similarity_score = 0.62

if similarity_score >= 0.8:
    relevance = "highly relevant"
elif similarity_score >= 0.5:
    relevance = "somewhat relevant"
else:
    relevance = "not relevant"

print(relevance)

Expected Output:

somewhat relevant

Visually, the routing logic branches like this:

graph TD
    Start([Check similarity_score]) --> Cond1{score >= 0.8}
    Cond1 -->|Yes| High["relevance = 'highly relevant'"]
    Cond1 -->|No| Cond2{score >= 0.5}
    Cond2 -->|Yes| Med["relevance = 'somewhat relevant'"]
    Cond2 -->|No| Low["relevance = 'not relevant'"]

How It Works

  • Python checks conditions top to bottom and runs the first block whose condition is True, then skips the rest entirely.
  • elif = “else if” — you can chain as many as you need.
  • else is optional and catches everything not already matched.

🤖 How Is This Used in AI?

  • Deciding whether a retrieved document is relevant enough to use
  • Deciding whether an API call succeeded, failed, or timed out
  • Routing an AI agent’s next action based on what a tool returned
  • Choosing which model to call based on a cost/complexity threshold
if response.get("error"):
    print("API call failed, will retry")
elif len(response.get("content", "")) == 0:
    print("Model returned an empty response")
else:
    print("Response looks good")

⚠️ Common Beginner Mistake:

if similarity_score = 0.8:   # SyntaxError

= assigns, == compares. This is one of the most common early bugs — Python will refuse to run at all until you fix it.

Key Takeaway: if/elif/else is how your program reacts to the real, messy, unpredictable output of the outside world — exactly what AI APIs produce.


2. Comparison and Logical Operators (recap in context)

score = 0.83
is_verified_source = True

# Comparison: produces a boolean
print(score > 0.75)                     # True

# Logical: combines booleans
print(score > 0.75 and is_verified_source)   # True
print(score > 0.75 or is_verified_source)    # True
print(not is_verified_source)                # False

Expected Output:

True
True
False

🤖 How Is This Used in AI? Filtering retrieved documents almost always looks like:

keep_document = (result["score"] >= 0.75) and (result["source"] != "spam")

This single line — comparisons combined with and/or — is the real filtering logic behind most RAG relevance thresholds.


3. for Loops

What Is It?

A for loop runs a block of code once for every item in a collection.

🧠 Intuition

A for loop is a conveyor belt — one item passes by at a time, and you do the same operation on each.

Syntax

for item in collection:
    # runs once per item, item holds the current value

Example

documents = [
    {"text": "Paris is the capital of France.", "score": 0.91},
    {"text": "The Eiffel Tower is in Paris.", "score": 0.85},
    {"text": "Bananas are yellow.", "score": 0.12},
]

relevant_docs = []

for doc in documents:
    if doc["score"] >= 0.5:
        relevant_docs.append(doc["text"])

print(relevant_docs)

Expected Output:

['Paris is the capital of France.', 'The Eiffel Tower is in Paris.']

How It Works

  • for doc in documents: takes each dictionary in documents, one at a time, and names it doc for that pass through the loop.
  • The if inside filters which ones get kept.
  • This pattern — loop + filter + collect — is called filtering, and it’s everywhere.

🤖 How Is This Used in AI?

  • Looping over retrieved search results to keep only relevant ones
  • Looping over tokens to count or process them
  • Looping over a batch of API requests to send one at a time
  • Looping over an agent’s tool outputs to decide the next step

⚠️ Common Beginner Mistake (indentation):

for number in [1, 2, 3]:
print(number)
# IndentationError: expected an indented block

Python uses indentation (spaces) to know what’s inside the loop. The fix:

for number in [1, 2, 3]:
    print(number)

enumerate() — looping with a position

for index, doc in enumerate(documents):
    print(f"[{index}] {doc['text']}")

Expected Output:

[0] Paris is the capital of France.
[1] The Eiffel Tower is in Paris.
[2] Bananas are yellow.

🤖 Useful for labeling chunks of a document, or numbering sources cited in an AI-generated answer.

Key Takeaway: If you’re doing “the same thing to many items,” you want a for loop.


4. while Loops

What Is It?

A while loop repeats as long as a condition stays True — unlike a for loop, it doesn’t know in advance how many times it’ll run.

🧠 Intuition

A for loop says “do this for each item in a known list.” A while loop says “keep doing this until something changes” — you don’t know the count ahead of time.

Example

retries = 0
max_retries = 3
success = False

while retries < max_retries and not success:
    print(f"Attempt {retries + 1}...")
    # pretend this simulates a failed API call
    success = False
    retries += 1

print("Gave up after", retries, "attempts" if not success else "")

Expected Output:

Attempt 1...
Attempt 2...
Attempt 3...
Gave up after 3 attempts

Visually, this retry logic repeats like this:

graph TD
    Start([Start Attempt]) --> Cond1{retries < max_retries AND not success}
    Cond1 -->|True| Call[Call API]
    Call --> Outcome{Success?}
    Outcome -->|Yes| SetSuccess[success = True]
    Outcome -->|No| Inc[retries += 1]
    SetSuccess --> Cond1
    Inc --> Cond1
    Cond1 -->|False| End([Exit Loop])

🤖 How Is This Used in AI?

  • Retry logic for flaky API calls (retry until success or max attempts)
  • Agent loops: “keep calling tools until the agent decides it has a final answer” — this is literally how many agent frameworks are built under the hood
  • Streaming: “keep reading chunks while more chunks are coming in”

[!IMPORTANT] Production Alert: Exponential Backoff and Jitter In production codebases, we never retry failed API calls instantly inside a tight loop. If the AI provider is rate-limiting you (raising HTTP 429 Too Many Requests), retrying immediately will only get you blocked longer.

Instead, production code uses exponential backoff (e.g. waiting 1s, then 2s, then 4s, doubling each time) and jitter (adding small random offsets to the wait time so that multiple parallel clients don’t all retry at the exact same millisecond). (We will cover how to code this in Module 11, but keep the concept of polite retries in mind!)

⚠️ Common Beginner Mistake — the infinite loop:

retries = 0
while retries < 3:
    print("trying...")
    # forgot to increment retries!

Without retries += 1, the condition never becomes False and the program runs forever. Always double-check that a while loop’s condition can eventually change.

Key Takeaway: Use while when you don’t know the number of repetitions in advance — you know the stopping condition instead.


5. break, continue, pass

documents = ["doc about python", "doc about cats", "doc about ai agents"]

# break: stop the loop entirely once found
for doc in documents:
    if "ai agents" in doc:
        print("Found it:", doc)
        break

# continue: skip this item, keep looping
for doc in documents:
    if "cats" in doc:
        continue   # skip irrelevant document
    print("Processing:", doc)

# pass: do nothing (a placeholder for code you'll write later)
for doc in documents:
    if "python" in doc:
        pass  # TODO: handle python-related docs later

Expected Output:

Found it: doc about ai agents
Processing: doc about python
Processing: doc about ai agents

🤖 How Is This Used in AI?

  • break: stop searching once the best-matching document is found
  • continue: skip documents below a relevance threshold without stopping the whole batch
  • pass: sketch out an agent’s decision branches before filling in the real logic — very common while designing agent control flow

6. Nested Loops

What Is It?

A loop inside another loop — useful when comparing every item of one collection against every item of another.

Example

queries = ["capital of France", "population of France"]
documents = ["Paris is the capital of France.", "France has about 68 million people."]

for query in queries:
    for doc in documents:
        # pretend this is a simple keyword-overlap "relevance" check
        query_words = set(query.lower().split())
        doc_words = set(doc.lower().split())
        overlap = query_words & doc_words
        if len(overlap) >= 2:
            print(f"'{doc}' matches '{query}'")

Expected Output:

'Paris is the capital of France.' matches 'capital of France'
'France has about 68 million people.' matches 'population of France'

🤖 How Is This Used in AI? Comparing every query against every document (a brute-force relevance check) is conceptually exactly what a vector search does at scale — just replaced with math (cosine similarity) instead of word overlap, and sped up with specialized data structures. The nested-loop version is the “naive but understandable” mental model.

⚠️ Common Beginner Mistake: Nested loops over large collections get slow fast (N × M operations). This is exactly why real AI systems use vector databases instead of comparing every item to every item in plain Python.


7. Practical Loop Patterns

Building a new list from an old one:

raw_scores = [0.2, 0.9, 0.75, 0.4, 0.88]
high_confidence = [s for s in raw_scores if s >= 0.7]
print(high_confidence)

Expected Output:

[0.9, 0.75, 0.88]

This is a list comprehension — a compact for loop that builds a list in one line. You’ll see this constantly in AI code (Module 4 covers it properly).

Counting matches:

count = 0
for score in raw_scores:
    if score >= 0.7:
        count += 1
print(count)   # 3

🤖 Both patterns show up constantly: filtering a batch of results, and counting how many passed a threshold (e.g., “how many chunks scored above 0.7?”).


Truthy and Falsy Values

An if statement can examine values that are not literally True or False. Python treats empty values such as "", [], {}, None, and numeric zero as falsy. Most non-empty values are truthy.

retrieved_documents = []

if retrieved_documents:
    print("Build an answer from the documents.")
else:
    print("No evidence was found.")

and and or also short-circuit: Python stops as soon as the answer is known. In user is not None and user.is_admin, the second check runs only if user exists. This prevents an error from asking None for .is_admin.

Visualizing One Loop

Ask collection for next item

Put item in loop variable

Run the indented body

More items? ── yes ──↺

     no

Continue after the loop

The collection is not duplicated. Python asks its iterator for one item at a time, which is why a loop can process generators and streamed results too.

Module Summary

You can now make your programs decide (if/elif/else), repeat over known data (for), repeat until a condition changes (while), and control loop behavior precisely (break, continue, pass).

AI Connection

Control flow is the decision-making layer of every AI application: filtering relevant documents, retrying failed API calls, looping through an agent’s reasoning steps, and processing collections of results — none of it happens without if and loops. The nested-loop query-matching example above is the simplest possible mental model for what a vector search engine does, just without the specialized math and indexing.

Mini Practice

  1. Given a list of scores, write an if/elif/else that labels each as "high", "medium", or "low" confidence.
  2. Write a for loop that builds a new list containing only documents longer than 20 characters.
  3. Write a while loop simulating retrying an API call up to 5 times, stopping early if success becomes True.
  4. Given a list of documents and a list of banned keywords, write nested loops that print any document containing a banned keyword, then break out of the inner loop as soon as one is found.
  5. Rewrite your Mini Practice #2 as a one-line list comprehension.

Next: Module 4 — Functions — turning these patterns into reusable, named building blocks (preprocessing, embedding, and inference functions).

Author
TechByteByByte Editorial Team
Reviewed by
TechByteByByte Admin
Published
Last reviewed