Step 43. Conditionals and Loops — Code That Decides and Repeats

Step 43. Conditionals and Loops — Code That Decides and Repeats

Level 1 — Programming and the Computer’s Inner Workings | Difficulty ★★☆☆☆ | Estimated time: 3.5 hours

Prerequisites: Steps 41–42 complete. You can handle variables, input/output, lists, and dictionaries.

  • What you need: the Step 41 workbench (Python + VSCode) and the basket knowledge from Step 42.
  • Caution: today’s exercise is 100% safe. However, in the infinite-loop experiment the program may not stop — press Ctrl + C to kill it.

So far, our programs flowed straight down, one line at a time. But the world’s work doesn’t only flow straight. "If it rains, take an umbrella; otherwise, just go out" (a decision), "keep knocking until the light goes off" (repetition). For a program to do real work, it needs these two forks in the road. Today’s if (the conditional fork) and for/while (loops) are exactly that. You can’t check 65,535 ports by hand, so a loop walks them for you; you can’t read a million log lines with your eyes, so a conditional filters out just the "suspicious lines." Today’s times table and number game are the practice boards for that skeleton.


1. Learning Objectives

By the end of this chapter, you will be able to:

  • Write programs that act differently based on conditions with if/elif/else
  • Follow the indentation rule (4 spaces) and fix an IndentationError
  • Build fixed-count and list-driven loops with for and range()
  • Build condition-escape loops with while and break/continue
  • Distinguish comparison operators (==, !=) from logical operators (and/or/not)
  • Assemble the log-filter pattern of "loop a list and filter by condition"

2. Background Knowledge — Today’s Tools and Concepts

Today’s Tools at a Glance

Category Details
Language/environment Python 3.12 or later, VSCode (the Step 41 workbench)
Today’s commands/grammar if/elif/else, indentation, for ~ in, range(), while, break, continue, ==/!=/</>=, and/or/not, % (remainder)
Concepts needed conditional expressions (true/false), code blocks and membership, boundary-value testing, infinite loops and Ctrl+C

2-1. if — The Signpost at the Fork

if means "if ~, then."

if score >= 60:
    print("Pass")

If the condition (score >= 60) is true, the indented line runs; if false, it’s skipped. When there are several forks, you chain elif (else if, "otherwise, if"), and when none match, else catches it. The final else is a safety net — there must be one place that accepts whatever value arrives, or the program falls into empty air.

2-2. Indentation — Python’s Proof of Membership

Python has no { } (curly braces) like other languages. Instead, indentation (4 spaces) marks "this line belongs to the if."

if score >= 60:
    print("Pass")            # belongs to the if (indented 4 spaces)
    print("Congratulations") # also belongs to the if
print("Good work")           # no indentation — unrelated to the if, always runs

Indentation is the proof of membership itself. Get the spaces wrong and Python refuses to run. It feels fussy at first, but thanks to this rule, Python code lines up straight no matter who writes it.

2-3. for — One by One from the Basket

for means "take the things in this basket out one by one and repeat."

for ip in ["1.1.1.1", "8.8.8.8"]:
    print(ip + " checking...")

Step 42’s list shines here. Work like "check a hundred IPs one by one" finishes in two lines. To loop by count, use range(). for i in range(5): loops five times with i changing through 0, 1, 2, 3, 4 — counting from 0 and dropping the end number, the same rule as slicing.

2-4. while — Until the Condition Ends

while means "keep going while the condition is true."

count = 0
while count < 3:
    print("Not enough yet")
    count = count + 1

Use it for loops where you don’t know the count in advance. But if the condition stays true forever, it loops forever (an infinite loop). So a while must always contain a device that eventually makes the condition false (the counter increment in the example above).

2-5. Comparison and Logical Operators

The comparison asking "equal?" is two equal signs (==). One equal sign (=) is assignment (attaching a name tag) — a completely different meaning. "Not equal" is !=. To bundle conditions, use and (both true), or (at least one true), and not (flip). % is the remainder of division; i % 2 == 0 is the test for even numbers.


3. Follow Along

3-1. First Fork — The Pass/Fail Judge

Create a file grade.py.

score = int(input("Score? "))
if score >= 60:
    print("You passed!")
else:
    print("Sorry, you didn't pass.")

Run it (verified on 2026-09-09):

Score? 72
You passed!

Entering 60 also prints "You passed!" (verified the same day). That’s because >= means "greater than or equal to," so 60 is included.

How to read it: don’t forget the colon (:) after the condition. The colon is the signal "the member lines come next," and else takes one too. And testing the boundary value (60, right on the cutoff) as you just did is a programmer’s basic habit. Most conditional bugs hide at the boundaries.

3-2. Several Forks — Assigning Grades

score = int(input("Score? "))
if score >= 90:
    print("A")
elif score >= 80:
    print("B")
elif score >= 70:
    print("C")
else:
    print("F")
Score? 95
A

(Verified on 2026-09-09.)

How to read it: it asks in order from the top, and once one is true, the rest are never asked. A 95 gets its A at the first gate and finishes. Order matters — as hands-on verification shows, if you flip the condition order to ask from 70 up and feed it 90, you get C (verified on 2026-09-09). The trick is to write conditions from the narrowest (highest bar) first.

3-3. for and Lists — Automatic Basket Processing

targets = ["192.168.0.1", "192.168.0.10", "192.168.0.20"]
for t in targets:
    print("Trying to connect to " + t + "...")
print("All checks complete")
Trying to connect to 192.168.0.1...
Trying to connect to 192.168.0.10...
Trying to connect to 192.168.0.20...
All checks complete

(Verified on 2026-09-09.)

How to read it: the last line has no indentation, so it runs only once, after the loop ends. A single level of indentation splits "what to do every time" from "what to do when done." This distinction is today’s core instinct. This pattern (list + for + process one by one) is the standard skeleton of scan scripts, log analysis, and batch file processing.

3-4. range and the Times Table

dan = int(input("Which table? "))
for i in range(1, 10):
    print(f"{dan} x {i} = {dan * i}")
Which table? 7
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63

(Verified on 2026-09-09.)

How to read it: range(1, 10) is from 1 up to just before 10 — that is, 1–9. Inside an f-string you can also write a computation like dan * i directly. With a third ingredient, range(2, 10, 2) makes 2, 4, 6, 8 (verified on 2026-09-09) — the third number is the "step."

3-5. while and break — The Number-Guessing Game

Today’s highlight. Create game.py.

answer = 42
while True:
    guess = int(input("Guess the number (1-100): "))
    if guess == answer:
        print("Correct! Congratulations!")
        break
    elif guess < answer:
        print("A bigger number (UP)")
    else:
        print("A smaller number (DOWN)")

Example run (entering 10 → 50 → 42) — verified on 2026-09-09:

Guess the number (1-100): 10
A bigger number (UP)
Guess the number (1-100): 50
A smaller number (DOWN)
Guess the number (1-100): 42
Correct! Congratulations!

How to read it: while True: has a condition that’s always true, so in principle it loops forever, and break (escape the loop) opens the door at the moment of the correct answer. "Loop forever, but escape when the condition is met" is the standard pattern for games, waiting, and retry logic. Also reconfirm the distinction between == (compare) and = (assign). These ten lines contain if, elif, else, while, break, and comparison all together.

3-6. continue and Bundling Conditions

"Skip just this turn" inside a loop is continue.

for i in range(1, 11):
    if i % 2 == 0:   # if even
        continue     # skip this turn
    print(i)
1
3
5
7
9

(Verified on 2026-09-09.)

How to read it: i % 2 == 0 is "remainder 0 when divided by 2" — the classic even-number test. break escapes the whole loop; continue escapes only this round. Keep the difference straight in your body.

Also check condition bundling.

age = int(input("Age? "))
member = input("Are you a member? (y/n) ")
if age >= 20 and member == "y":
    print("An adult member — welcome!")

and passes only when both conditions are true. Change it to or, run it, and feel the difference.

3-7. Real-World Mini Project — Filtering Suspicious Log Lines

Let’s put everything learned today into one program: a filter that extracts only "suspicious lines" from a fake log. filter.py:

logs = [
    "192.168.0.5 GET /index.html 200",
    "10.0.0.7 GET /admin 404",
    "192.168.0.5 GET /style.css 200",
    "10.0.0.7 GET /admin/login 404",
    "192.168.0.9 GET /index.html 200",
    "10.0.0.7 POST /admin/delete 403",
]
count = 0
for line in logs:
    parts = line.split(" ")
    ip = parts[0]
    path = parts[2]
    status = parts[3]
    if "admin" in path and status != "200":
        count = count + 1
        print(f"Suspicious: {ip} tried {path} -> {status}")
print(f"Found {count} suspicious accesses in total.")
Suspicious: 10.0.0.7 tried /admin -> 404
Suspicious: 10.0.0.7 tried /admin/login -> 404
Suspicious: 10.0.0.7 tried /admin/delete -> 403
Found 3 suspicious accesses in total.

(Verified on 2026-09-09.)

How to read it: Step 42’s split and indexing, today’s for and if, the and combination, and the counter pattern (count = count + 1) are all in here. != means "not equal." These twenty lines are the bare skeleton of a log-analysis script.

Predict, then verify: if you change the condition to just status == "403", how many lines get caught? Write it in your notebook before running, then check. This is training to feel how a single condition difference changes the result.


4. Missions & Exercises

Mission — Upgraded Number-Guessing Game

Add the following three features to the game from 3-5 to complete game2.py.

  1. Make the answer change every run. Hint: write import random at the top of the file and change the answer to random.randint(1, 100). import brings in a part made by someone else, and random is a built-in Python part.
  2. Count the attempts and print something like Solved in 5 tries! on success. Hint: create tries = 0 above the while, and do tries = tries + 1 on each guess.
  3. If the player passes 7 tries, print Out of chances! and end. Hint: a tries >= 7 condition and break.

After achieving all three requirements, deliberately miss 7 times and verify the termination path too.

Exercises

Question 1. In the code below, how many times does print("done") run? Explain the reason in terms of indentation.

for i in range(3):
    print(i)
print("done")

Question 2. Why is if guess = answer: an error, and what error does it actually produce?

Question 3. For a loop made with while True: to ever end, what device is needed? When a program without that device won’t stop, how do you kill it in the terminal?

Question 4. With a score of 90, if you write the conditions in the order if score >= 70: ... elif score >= 80: ... elif score >= 90: ..., which grade comes out and why? What is the correct writing trick?


5. Model Answers & Completion Criteria

Mission Model Answer

import random

answer = random.randint(1, 100)
tries = 0

while True:
    guess = int(input("Guess the number (1-100): "))
    tries = tries + 1

    if tries >= 7:
        print("Out of chances!")
        break

    if guess == answer:
        print(f"Correct! Solved in {tries} tries!")
        break
    elif guess < answer:
        print("A bigger number (UP)")
    else:
        print("A smaller number (DOWN)")

Commentary: ① random.randint(1, 100) draws a different integer between 1 and 100 every time. ② tries is the counter pattern: it starts at 0 outside the loop and grows by 1 per guess. ③ The chances-exhausted check must sit right after the guess so that "the 7th input" still gets judged. Reordering things to test the rules is also good practice.

How to verify: ① Run it twice and see whether the answer differs. ② Enter guesses until correct and see whether the tries message appears. ③ Deliberately enter wrong numbers 7 times and see whether "Out of chances!" appears and the program ends. When all three paths check out, you’re done.

Exercise Answers

Answer 1. It runs once. Since print("done") has no indentation, it doesn’t belong to the for — it’s an independent line that runs once after the loop ends. Only print(i) prints three times: 0, 1, 2.

Answer 2. = is assignment (attaching a name tag) while comparison is ==, and Python outright blocks assignment inside an if as an error. The actual error looks like this (verified on 2026-09-09):

  File "...\s43_eqeq.py", line 3
    if guess = answer:
       ^^^^^^^^^^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

That it even attaches the suggestion "maybe you meant ==" is recent Python’s kindness.

Answer 3. You need a device inside the loop that eventually makes the condition false (a counter increment) or a break. A program that won’t stop without such a device is force-quit in the terminal with Ctrl + C. It’s the emergency brake meaning "stop the running program now."

Answer 4. C comes out. It asks in order from the top, and 90 passes the first condition >= 70 right away; once one passes, the rest are never asked (verified on 2026-09-09). The trick is to write the narrower condition (higher bar) higher up.

Completion Criteria Checklist

  • [ ] I can build forks with if/elif/else, writing narrow conditions first
  • [ ] I can express membership with indentation (4 spaces) and fix an IndentationError
  • [ ] I can write both loops: for + list and for + range()
  • [ ] I can build the "escape when condition met" pattern with while True + break
  • [ ] I know the difference between break (escape entirely) and continue (escape this round)
  • [ ] I distinguish == from = and know the habit of testing boundary values (like 60)
  • [ ] I completed all three mission requirements (game2.py) and verified the three paths

6. Common Pitfalls & Fixes

Wall 1. I get an IndentationError

Symptom (verified on 2026-09-09):

  File "...\s43_indent.py", line 3
    print("Pass")
    ^^^^^
IndentationError: expected an indented block after 'if' statement on line 2

Cause: you didn’t indent the line after the if‘s colon, or you mixed spaces and tabs. The message’s "expected an indented block after the if on line 2" is the diagnosis verbatim.
Fix: the line after the colon of if/for/while gets 4 spaces, no exceptions. Align lines using VSCode’s indentation guides, and if tabs got mixed in, erase and rewrite with spaces only.

Wall 2. I’m stuck in an infinite loop

Symptom: the program never ends and keeps printing the same thing.
Cause: the while‘s condition stays true forever with no break, or you omitted the line that changes the condition (the counter increment).
Fix: force-quit with Ctrl + C. Then check whether the while contains "a line that eventually makes the condition false."

Wall 3. Confusing = and ==

Symptom: SyntaxError at if guess = answer: (see section 5, Question 2 for the verified message).
Cause: you assigned (=) inside an if. Comparison is ==.
Fix: memorize it as "asking? ==. Ordering? =." Two equal signs makes an asking sentence; one makes a commanding sentence.

Wall 4. Conditions always fall through to else

Symptom: you clearly entered 90 but got an F.
Cause: typically two things. Either the score wasn’t converted with int() so text is being compared to text (Step 41’s trap), or the condition order is flipped.
Fix: check with print(type(score)) whether the variable is a number (<class 'int'>) or text (<class 'str'>) (verified on 2026-09-09: the two printed as <class 'str'> and <class 'int'> respectively). type() is the function that asks "what kind of content is in this box?" Also check whether conditions are written narrow-first.

Wall 5. The code doesn’t do what I mean, and I can’t find the cause

Symptom: no error, but the result is strange.
Cause: the execution order in your head differs from Python’s actual execution order.
Fix: the most powerful debugging tool a beginner can use is print. At the spot where you wonder "what’s the variable here?", insert print(f"i is now {i}"). The execution flow and value changes become visible as-is. An expert’s debugger ultimately does the same thing — stop, look inside, check line by line.


7. Summary

Today’s Concepts

Concept One-line description
Conditional expression A sentence that answers true/false (score >= 60)
Indentation 4 spaces — Python’s proof of membership
Code block Member lines bundled by the same indentation
Counter pattern Count with count = 0 then count = count + 1
Infinite loop A loop whose condition stays true forever — stop with Ctrl+C
Boundary-value test The habit of testing the cutoff itself (like 60)

Today’s Grammar

Grammar What it does
if / elif / else Conditional forks — narrow first, safety net last
for x in list: Repeat one by one from the basket
range(a, b) / range(a, b, step) A sequence of numbers from a up to before b
while condition: Repeat while the condition is true
break / continue Escape the whole loop / escape this round only
==, !=, <, >= Comparison (distinguish from assignment =)
and / or / not Bundle conditions / flip
% Remainder — i % 2 == 0 means even

Instincts More Important Than Grammar

The skeleton of a security script is "loop a list (for) and filter by condition (if)," and today’s log filter is that skeleton in the nude. The times table and the number game may look like child’s play, but their structure is exactly the same as a ten-thousand-line analysis tool. Automation amplifies power, which makes direction all the more important. ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime.

Conditions and loops are not talent — they’re muscle. Every line you typed today is the first set of that muscle.


Once every box is checked, Step 43 is complete. Click the checkbox in the sidebar to save your progress.