Sitemap
Ajay Narayan

Ajay Narayan

Just a Python enthusiast sharing what I learn and discover along the way.

Press enter or click to view image in full size
Photo by on

Why Write Code Once When It Can Just… Repeat?

8 min readSep 11, 2026

--

Hey again! 👋

Quick question before we start: in the last post, when we built that number guessing game, did you notice something weird?

We didn’t know how many times the player would guess. Could be 1 attempt. Could be 7. We didn’t write if guess == secret_number seven separate times and hope for the best — the code just kept asking, and asking, and asking, until something made it stop.

That “keep doing this until…” behavior? That was a loop. You already used one. You just didn’t know its name yet.

Today we’re going to actually understand it — and then go way further than that game did.

Because here’s the thing about computers: they’re really, really good at doing boring, repetitive things without complaining. Printing something 1,000 times? Checking every item in a list? Retrying a failed connection until it works? That’s not a computer’s weakness — that’s its entire superpower. Loops are how you unlock it.

What You’ll Master Today

By the end of this post, you’ll be able to:

✅ Use while loops to repeat code based on a condition ✅ Use for loops to repeat code a set number of times, or over a collection ✅ Control loops with break and continue ✅ Recognize the accumulator and counter patterns you'll use constantly ✅ Build a play-again version of our guessing game ✅ Know exactly when to reach for while vs. for

Prerequisites: Variables & Data Types, Operators, and Control Flow (yep, all three previous posts — loops lean on everything we’ve built so far).

Part 1: The while Loop — Keep Going Until I Say Stop

Think about brushing your teeth. You don’t count “one brush, two brush, three brush.” You just brush while it still feels like there’s more to do, then you stop.

That’s a while loop.

count = 1
while count <= 5:
print(f"Count: {count}")
count += 1
# Output:
# Count: 1
# Count: 2
# Count: 3
# Count: 4
# Count: 5

What’s actually happening here, step by step:

  1. Python checks the condition (count <= 5)
  2. If it’s True, it runs the code inside the loop
  3. Then it goes back and checks the condition again
  4. This repeats until the condition becomes False

Notice that count += 1 line? That's not decoration — that's the whole engine of the loop. Without it, count would stay at 1 forever, the condition would always be True, and you'd have what's politely called an infinite loop and impolitely called "why is my laptop fan suddenly very loud."

Let’s actually see that happen on purpose (don’t run this one):

# DO NOT RUN THIS
count = 1
while count <= 5:
print(f"Count: {count}")
# forgot to increment count!
# This prints "Count: 1" forever, because count never changes

The rule that saves you: every while loop needs something inside it that eventually makes the condition False. If you can't point to that line, you've probably written an infinite loop.

Real-World: Login Attempt Limiter

Here’s somewhere while genuinely earns its keep — you don't know in advance how many tries someone will need:

print("Login System")
print("-" * 40)
correct_password = "python123"
attempts = 0
max_attempts = 3
while attempts < max_attempts:
entered = input("Enter password: ")
attempts += 1
if entered == correct_password:
print("Login successful!")
break
else:
remaining = max_attempts - attempts
if remaining > 0:
print(f"Wrong password. {remaining} attempt(s) left.")
else:
print("Account locked. Too many failed attempts.")
# Example run:
# Enter password: hello
# Wrong password. 2 attempt(s) left.
# Enter password: letmein
# Wrong password. 1 attempt(s) left.
# Enter password: python123
# Login successful!

See that break in there? We'll come back to it properly in Part 3 — but notice how it lets us exit the loop the moment we succeed, instead of waiting around for the condition to naturally go false.

Part 2: The for Loop — When You Know What You're Looping Over

while is great for "keep going until something happens." But a lot of the time, you already know exactly what you want to repeat over — five items, ten rounds, every letter in a word. For that, Python gives you something more direct: for.

for i in range(5):
print(f"Iteration: {i}")
# Output:
# Iteration: 0
# Iteration: 1
# Iteration: 2
# Iteration: 3
# Iteration: 4

First surprise for most beginners: range(5) gives you 0, 1, 2, 3, 4 — five numbers, starting at 0, not including 5. This trips up almost everyone once. Now it won't trip you up at all.

range() is more flexible than it looks:

# range(start, stop)
for i in range(1, 6):
print(i)
# 1, 2, 3, 4, 5
# range(start, stop, step)
for i in range(0, 10, 2):
print(i)
# 0, 2, 4, 6, 8

But for isn't just for counting numbers — it's for going through things:

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(f"I like {fruit}")
# Output:
# I like apple
# I like banana
# I like cherry

Read that like a sentence: “for each fruit in fruits, do this.” That’s genuinely all it’s doing.

Strings work too, because a string is really just a sequence of characters:

name = "Ajay"
for letter in name:
print(letter)
# Output:
# A
# j
# a
# y

Real-World: Multiplication Table Generator

print("Multiplication Table Generator")
print("-" * 40)
number = int(input("Enter a number: "))for i in range(1, 11):
result = number * i
print(f"{number} x {i} = {result}")
# Example run:
# Enter a number: 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
# 7 x 10 = 70

Ten lines of output from three lines of code. That’s the whole pitch for loops, right there.

while vs for — How to Actually Decide

This is the question I get asked the most, so let’s settle it:

  • Use for when you know how many times you're repeating, or you're going through a collection (a list, a string, a range of numbers).
  • Use while when you're repeating until a condition changes — and you don't know in advance how long that'll take (like waiting for correct input, or playing a game until someone wins).

Rule of thumb: if you could say “for each ___, do this,” reach for for. If you'd say "keep doing this until ___," reach for while.

Part 3: break and continue — Changing the Loop's Mind Mid-Run

Sometimes you don’t want to wait for the loop to finish naturally. You want to jump out early, or skip just this one round. That’s what break and continue are for.

Get Ajay Narayan’s stories in your inbox

Join Medium for free to get updates from this writer.

break — stop the loop completely:

for number in range(1, 11):
if number == 6:
print("Found 6! Stopping here.")
break
print(number)
# Output:
# 1
# 2
# 3
# 4
# 5
# Found 6! Stopping here.

Notice 6 through 10 never print. The moment break runs, the loop is over — no more checking, no more looping.

continue — skip this round, keep going:

for number in range(1, 11):
if number % 2 == 0:
continue # skip even numbers
print(number)
# Output:
# 1
# 3
# 5
# 7
# 9

continue doesn't end the loop — it just says "skip the rest of this round and move to the next one." That's why the odd numbers still print, just not the even ones.

The difference in one sentence: break says "I'm done, exit now." continue says "not this one, next please."

Real-World: Search Until Found

print("Contact Search")
print("-" * 40)
contacts = ["Alice", "Bob", "Charlie", "Diana", "Ethan"]
search_name = input("Search for a contact: ")
found = False
for contact in contacts:
if contact.lower() == search_name.lower():
print(f"Found: {contact}")
found = True
break
if not found:
print(f"'{search_name}' not in contacts.")
# Example 1:
# Search for a contact: charlie
# Found: Charlie
# Example 2:
# Search for a contact: Zoe
# 'Zoe' not in contacts.

Once we find the name, there’s no reason to keep checking the rest of the list — break gets us out immediately.

Part 4: Two Patterns You’ll Use Constantly

Almost every loop you write for the rest of your life will lean on one of these two patterns. Learn them now and a lot of future code will feel obvious instead of confusing.

The counter pattern — track how many times something happened:

numbers = [3, -7, 12, -2, 8, -1, 5]
negative_count = 0
for num in numbers:
if num < 0:
negative_count += 1
print(f"Negative numbers found: {negative_count}")
# Output: Negative numbers found: 3

The accumulator pattern — build up a total (or a new list) as you go:

numbers = [3, 7, 12, 2, 8, 1, 5]
total = 0
for num in numbers:
total += num
print(f"Sum: {total}")
# Output: Sum: 38

Same idea, but building a list instead of a number:

numbers = [3, -7, 12, -2, 8, -1, 5]
positives = []
for num in numbers:
if num > 0:
positives.append(num)
print(f"Positive numbers: {positives}")
# Output: Positive numbers: [3, 12, 8, 5]

Notice the shape of both patterns: start with an empty value (0 or []) before the loop, then update it inside the loop, every round. That "start empty, update every round" shape is worth memorizing — you'll type it hundreds of times.

Mini Project: Number Guessing Game 2.0

Remember the guessing game from last time? It’s about to get a lot more interesting — this version tracks your best score and lets you play again without restarting the program.

import random
def play_round():
secret_number = random.randint(1, 100)
attempts = 0
max_attempts = 7
print("\nI'm thinking of a number between 1 and 100.")
print(f"You have {max_attempts} attempts to guess it!\n")
while attempts < max_attempts:
guess = int(input(f"Attempt {attempts + 1}/{max_attempts} - Guess: "))
attempts += 1
if guess == secret_number:
print(f"\nYOU WON in {attempts} attempts!")
return attempts
elif guess < secret_number:
print("Too low! Try higher.")
else:
print("Too high! Try lower.")
print(f"\nGAME OVER! The number was {secret_number}.")
return None

print("=" * 50)
print("NUMBER GUESSING GAME 2.0")
print("=" * 50)
best_score = None
games_played = 0
while True:
result = play_round()
games_played += 1
if result is not None:
if best_score is None or result < best_score:
best_score = result
print("New best score!")
if best_score is not None:
print(f"Best score so far: {best_score} attempts")
play_again = input("\nPlay again? (yes/no): ").lower()
if play_again != "yes":
break
print(f"\nThanks for playing! Games played: {games_played}")

Look at what changed: an outer while True loop keeps the whole game running round after round, and it only stops when the player types anything other than "yes." That while True pattern — loop forever, break on purpose when you're ready to stop — is everywhere in real code, from game loops to servers waiting for requests.

Practice Challenges

Beginner Level

  1. Countdown Timer: Use a while loop to print numbers from 10 down to 1, then print "Liftoff!"
  2. Even Number Printer: Use a for loop with range() to print all even numbers from 1 to 50.

Intermediate Level

  1. Sum of Digits: Ask for a number. Use a loop to add up its individual digits (hint: you can loop over it as a string, or use % and //).
  2. Vowel Counter: Ask for a word. Loop through it and count how many vowels it contains.

Advanced Level

  1. Prime Number Checker: Ask for a number. Use a loop (and what you know about %) to determine if it's prime. Then extend it to print all primes up to that number.

Before You Go

Did loops click for you? Hit that 👏 clap button.

Built the guessing game 2.0? Drop your best score in the comments — let’s see who can win in the fewest attempts.

Want the next post instantly? Hit Follow to get notified.

See you in the next post! 🐍✨

Enjoying this series? Share it with a friend learning Python. Let’s all grow faster, together.

Check out the series so far:

--

--

Written by Ajay Narayan

Just a Python enthusiast sharing what I learn and discover along the way.