Python, Concept by Concept

unit

Loops & Counting

A space probe starts with the number 27. If the number is even, the probe divides it by 2. Otherwise it triples the number and adds 1. It repeats until the number reaches 1.

The mission board needs one summary line:

Steps: 111

How can one small block of code repeat without being copied 111 times?

We will build that payoff in three lessons. First we repeat with while, then collect totals and counts, and finally stop when a calculated value reaches a goal.

You will learn

  • Repeat instructions with a while loop and count its passes.
  • Keep a running total or count only values that meet a condition.
  • Stop a loop when a changing value reaches a goal, or leave early with break.
  • Check the boundary and update so a loop stops at the right time.

Lesson 1: Repeat and Keep Count

Reassignment comes first

A loop counter depends on reassignment: calculate a new value from the saved value, then save the result back under the same name.

Run this rung before writing a loop.

count = 0
count = count + 1
print(count)

Output

1

Notice

In count = count + 1, Python computes the right side with the OLD value of count, then saves the new value. Lesson 2 teaches the shorter += form for accumulators.

A while loop

A while loop repeats its indented body while its condition is True. A loop counter records how many passes have happened.

Minimal: count three passes, then print one summary.

count = 0

while count < 3:
    count = count + 1

print(f"Count: {count}")

Output

Count: 3

Notice

The counter starts at 0, changes once each pass, and eventually makes count < 3 false. That change is what guarantees the loop stops.

One twist: output can happen during each pass.

number = 1

while number <= 5:
    line = f"Number: {number}"
    print(line)
    number = number + 1

Output

Number: 1
Number: 2
Number: 3
Number: 4
Number: 5

Notice

All four spaces of indentation belong to the loop. The update happens after printing, so the visible numbers are 1 through 5.

When the counter never changes

This broken example forgets i = i + 1. Read it, but do not run it.

Watch out: this never stops

i = 0

while i < 5:
    print(i)

Notice

i stays 0, so the condition stays true forever. If you accidentally run an infinite loop, choose Kernel → Interrupt in Jupyter or press Ctrl-C in a terminal. Then add the missing update before running again.

i = 0

while i < 5:
    print(i)
    i = i + 1

Output

0
1
2
3
4

Notice

Now i advances toward 5, so the loop prints 0 through 4 and stops.

Repair an off-by-one boundary

A loop can stop safely but still include one too few or one too many values. Compare the two boundaries.

i = 0

while i < 5:
    print(i)
    i = i + 1

Output

0
1
2
3
4

Notice

i < 5 prints 0, 1, 2, 3, 4. It stops before 5. Use <= when 5 itself must be included.

i = 0

while i <= 5:
    print(i)
    i = i + 1

Output

0
1
2
3
4
5

Notice

i <= 5 prints 0 through 5. Reading the expected first and last values helps repair an off-by-one mistake.

Try real input: type a starting number to count down to liftoff.

Try it yourself

number = int(input("Start: "))
while number > 0:
    print(number)
    number = number - 1
print("Liftoff!")

Notice

int() turns the typed text into a number; decreasing it reaches zero and ends the loop.

Read a real NameError

A counter or total must exist before the program can update it. The broken cell uses total before total = 0. Read the final traceback line, then run the fixed partner.

Read the error

number = 7
total = total + number
print(f"Total: {total}")

The traceback ends with NameError: name 'total' is not defined. Python cannot add to a value that has never been saved. Add the initializer before the update.

number = 7
total = 0
total = total + number
print(f"Total: {total}")

Output

Total: 7

Notice

The initializer gives total a starting value. This traceback beat is different from an infinite loop: a NameError stops with a message, while a logic mistake can keep running.

Lesson 2: Accumulate Totals and Counts

A running total

An accumulator saves a result that grows one pass at a time. A running total starts at 0, adds the current number, and saves the result back into total.

Minimal: add the integers from 1 through 10.

number = 1
total = 0

while number <= 10:
    total = total + number
    number = number + 1

print(f"Sum: {total}")

Output

Sum: 55

Notice

total must begin at 0 because 0 changes no sum. The loop prints one summary after all ten additions.

One twist: shorten the update of a running total with +=.

number = 1
total = 0
while number <= 4:
    total += number
    number = number + 1
print(f"Sum: {total}")

Output

Sum: 10

Notice

total += number means the same as total = total + number; the total is 10.

Realistic: now add all the integers from 1 through 100.

number = 1
total = 0

while number <= 100:
    total = total + number
    number = number + 1

print(f"Sum: {total}")

Output

Sum: 5050

Notice

The result is Sum: 5050. The counter chooses each number once; the accumulator remembers the growing sum.

Count by a condition

Sometimes we do not add the values themselves. Instead, we add 1 only when a value passes a test. That pattern is count by condition.

number = 1
count = 0

while number <= 20:
    if number % 3 == 0:
        count = count + 1
    number = number + 1

print(f"Count: {count}")

Output

Count: 6

Notice

Every number is checked, but the counter changes only for 3, 6, 9, 12, 15, and 18. The summary is Count: 6.

One twist: an elif ladder can count several tiers in the same walk.

score = 1
low_count = 0
middle_count = 0
high_count = 0

while score <= 10:
    if score >= 8:
        high_count = high_count + 1
    elif score >= 4:
        middle_count = middle_count + 1
    else:
        low_count = low_count + 1
    score = score + 1

print(f"Low: {low_count}")
print(f"Middle: {middle_count}")
print(f"High: {high_count}")

Output

Low: 3
Middle: 4
High: 3

Notice

Exactly one branch counts each score. Checking the highest tier first produces 3 low, 4 middle, and 3 high scores.

Try real input: type one whole number per line; a zero ends the collection.

Try it yourself

number = int(input("Number (0 to stop): "))
total = 0
while number != 0:
    total = total + number
    number = int(input("Number (0 to stop): "))
print(f"Sum: {total}")

Notice

The first read sets the condition, and each pass reads again so a typed 0 stops the loop.

Products and digit totals

A factorial multiplies the integers from 1 through n. Its accumulator must start at 1, not 0, because multiplying by 0 would erase the whole product. Keep n at 10 or below in this unit.

n = 5
number = 1
product = 1

while number <= n:
    product = product * number
    number = number + 1

print(f"Product: {product}")

Output

Product: 120

Notice

product = 1 preserves the first multiplication. The summary is Product: 120.

Minimal: count how many digits remain when a positive number is peeled one digit at a time.

n = 4827
digits = 0
while n != 0:
    n = n // 10
    digits = digits + 1
print(f"Digits: {digits}")

Output

Digits: 4

Notice

Four divisions remove all four digits; the loop prints Digits: 4.

One twist: add each peeled digit instead of counting it.

n = 4827
digit_total = 0

while n != 0:
    digit = n % 10
    digit_total = digit_total + digit
    n = n // 10

print(f"Digit sum: {digit_total}")

Output

Digit sum: 21

Notice

n becomes 482, then 48, then 4, then 0. Reaching 0 is a calculated stop value, and the digit sum is 21.

One twist: keep the best digit seen so far while peeling.

n = 4827
best = 0
while n != 0:
    digit = n % 10
    if digit > best:
        best = digit
    n = n // 10
print(f"Largest digit: {best}")

Output

Largest digit: 8

Notice

best changes only when a larger digit appears, so the final result is 8.

Lesson 3: Stop at a Computed Goal

A plain-condition sentinel

A sentinel loop repeats until a computed stop value appears. Begin with the plain condition while n != 1. For the Collatz rule below, every shown starting value is a positive integer chosen to reach 1.

n = 6
steps = 0

while n != 1:
    if n % 2 == 0:
        n = n // 2
    else:
        n = n * 3 + 1
    steps = steps + 1

print(f"Steps: {steps}")

Output

Steps: 8

Notice

steps is the one source of truth: it counts each update and supplies the printed summary Steps: 8. The condition states the stop goal directly.

Try real input: enter a positive starting value and count its Collatz updates.

Try it yourself

n = int(input("Start: "))
steps = 0
while n != 1:
    if n % 2 == 0:
        n = n // 2
    else:
        n = n * 3 + 1
    steps = steps + 1
print(f"Steps: {steps}")

Notice

The typed value replaces the fixed start; each update counts one step before the loop checks again.

Exit from the middle with break

A loop can have an ordinary boundary and still leave early when a result is found. First try break inside while n <= 100:.

Minimal: leave an ordinary bounded loop as soon as the first square exceeds 300.

n = 1
while n <= 100:
    if n * n > 300:
        break
    n = n + 1
print(f"{n} squared is {n * n}")

Output

18 squared is 324

Notice

The first match is 18, and break leaves the loop before the next increment.

One twist: while True: has no boundary in its header, so its reachable break must provide the exit.

value = 3
steps = 0

while True:
    value = value * 2
    steps = steps + 1
    if value > 1000:
        break

print(f"Steps: {steps}")

Output

Steps: 9

Notice

Positive doubling must eventually pass 1000, so the break is reachable. The summary is Steps: 9. Never write while True: unless you can explain why its break will be reached.

Try real input: play a human guessing game. Enter guesses until you find the secret 42.

Try it yourself

secret = 42
guesses = 0
while True:
    guess = int(input("Guess: "))
    guesses = guesses + 1
    if guess == secret:
        break
    if guess < secret:
        print("Too low")
    else:
        print("Too high")
print(f"Found {secret} in {guesses} guesses")

Notice

Only a correct guess reaches break; every typed guess counts once. The exercise robot later chooses guesses by itself.

Greatest common divisor by subtraction

For positive integers, any common divisor of a and b also divides a - b. That lets us replace the larger value with the difference until both values match.

A trace for (48, 18) is (30, 18), (12, 18), (12, 6), (6, 6). The matching value is the greatest common divisor.

a = 48
b = 18

while a != b:
    if a > b:
        a = a - b
    else:
        b = b - a

print(f"GCD: {a}")

Output

GCD: 6

Notice

Each subtraction keeps the common divisors but shrinks the larger positive value. The process stops at GCD: 6. A faster remainder-based version is saved as a later Challenge.

Final build

Return to the probe mission. The fixed start value is 27, and the loop stops only when the computed value reaches 1. Run the build and check the single summary line.

# Count the updates from 27 until the value reaches 1.
n = 27
steps = 0

while n != 1:
    if n % 2 == 0:
        n = n // 2
    else:
        n = n * 3 + 1
    steps = steps + 1

print(f"Steps: {steps}")

Output

Steps: 111

Notice

The build prints Steps: 111. The plain while n != 1: condition stops the loop when the changing value reaches 1; steps records every update and supplies the summary.

Recap

  • while repeats while its condition is true; update the value that controls it.
  • A counter records passes, and an accumulator keeps a growing result.
  • Add 1 only when a value passes a test to count matching values.
  • A changing stop value can end a loop; break can leave early.
  • Check the first and last values to catch an off-by-one mistake.

You can now count the steps in the space probe's number journey.

Go to the exercises (34)

For parents and teachers: report a problem