Browse this section
Browse these items

All writing

Details and outline
Kind
Essay
Published
27 October 2026
Length
4 min read
Authorship
Created, drafted, and interpreted by Claude
Model
Claude Sonnet 5.5

AI disclaimer: this page was written for the site owner to read occasionally. AI can make mistakes, so the content may be inaccurate. Please read it with caution. The site owner does not recommend making any decision based on AI-generated content.

Essay

Learning Python, Part 2: Decisions and Loops

Study notes on comparisons, if and elif, for and while loops, accumulators and nested loops, with invented examples. Written entirely by an AI model.

Part 1 covered values. This part is about control: choosing between actions, and repeating them.

Comparisons and logic

The six comparisons are ==, !=, <, <=, > and >=. Each gives True or False. A single = is assignment, so if x = 5: is a syntax error rather than a comparison.

  • Python allows chains: 0 < x < 10 means 0 < x and x < 10.
  • Strings compare by Unicode code point, one character at a time. Capitals sort before lowercase letters, so "Zebra" < "apple" is True.
  • Mixing types raises TypeError: "5" < 6 fails.

and, or and not combine conditions. Precedence runs not, then and, then or; add brackets rather than rely on memory. They also short-circuit, which makes this guard safe:

if i < len(word) and word[i] == "x":
    print("found at", i)

When i is too large, the first test is False and the second is never evaluated, so there is no IndexError.

if, elif and else

def ticket_price(age):
    if age < 4:
        return 0
    elif age < 13:
        return 8
    elif age < 65:
        return 15
    else:
        return 10

Python tests the branches from top to bottom and runs the first one that is true. Everything after that is skipped, which means order matters. Swap the first two branches so the test is age < 13 before age < 4, and toddlers pay 8 instead of nothing, because the broader test catches them first. Put the most specific test first.

Use plain if statements, not elif, when several conditions can all be true at once and you want every matching action to run.

Decisions are also your first line of defence against crashes. Check for the dangerous case before you divide, index or take a square root:

def share(total, people):
    if people == 0:
        return None
    return total / people

for loops and range

A for loop runs its body once per item in a sequence:

for colour in ["red", "gold", "jade"]:
    print(colour.upper())

When you need counting, use range:

  • range(5) gives 0, 1, 2, 3, 4.
  • range(2, 5) gives 2, 3, 4.
  • range(10, 0, -3) gives 10, 7, 4, 1.

The stop value is never included. A step of zero raises ValueError, and an empty range such as range(5, 2) simply runs the body zero times.

The accumulator pattern

Most loops build up a result, and they all follow the same four steps:

  1. Start a variable at the identity for the operation: 0 for a sum, 1 for a product, "" for text, [] for a list.
  2. Loop over the inputs.
  3. Update the variable inside the loop.
  4. Use it after the loop.
def savings_after(years, deposit, rate):
    jar = 0.0
    for year in range(years):
        jar = (jar + deposit) * (1 + rate)
    return jar

print(round(savings_after(3, 100, 0.05), 2))   # 331.01

A habit worth building: trace a loop on paper with a small table before running it.

Pass year jar after
1 0 105.0
2 1 215.25
3 2 331.0125

If your accumulator starts at the wrong value, every answer is wrong in the same predictable way. That makes the table a quick way to find the mistake.

while loops

Use while when you do not know in advance how many passes you need.

def halvings(amount, floor):
    steps = 0
    while amount >= floor:
        amount = amount / 2
        steps += 1
    return steps

print(halvings(100, 1))   # 7

The two risks with while are a condition that never becomes false (an infinite loop) and a condition that is false from the start, so the body never runs. Make sure something inside the loop moves the condition towards false.

Three shapes come up repeatedly:

  • Interactive loop. Ask “again?” after each pass.
  • Sentinel loop. Keep reading values until a special one, such as an empty line, signals the end.
  • Post-test loop. Run the body at least once, then decide. Python has no do...while, so write while True: and break when the exit condition is met.
total = 0
while True:
    line = input("Add a number (blank to stop): ")
    if line == "":
        break
    total += float(line)
print("Total:", total)

break leaves the loop. continue skips straight to the next pass.

Nested loops

An inner loop runs completely for every pass of the outer one.

for row in range(1, 4):
    for col in range(1, 5):
        print(row * col, end="\t")
    print()

The inner body runs 3 × 4 = 12 times. The bare print() at the end of each row ends the line.

A classic use is testing whether a number is prime by trying divisors:

def is_prime(n):
    if n < 2:
        return False
    d = 2
    while d * d <= n:
        if n % d == 0:
            return False
        d += 1
    return True

Only divisors up to the square root need checking. If n has a factor larger than that, it also has a matching factor smaller than it.

Where to practise

Try Set A in Python Drills, section 2 (“Loops, recursion and nesting”). The bouncing-ball drill is a while loop with an accumulator. The packing drill in section 3 is a nested loop with a flag. Part 3 turns these ideas into reusable functions.