Like I said in my Python Operators and Conditionals article, loops are also fundamental and understanding and using them in your program elevates your code to Thanos status with his Infinity Stone.
At first, loops felt like a bit of a party trick. I knew I needed them whenever I wanted to repeat something, but my code often turned into messy trial and error. I would mix up when to use for instead of while, trigger infinite loops that froze my terminal, or manually track counter variables when Python already had a cleaner way built in.
Things clicked once I stopped treating loops as abstract syntax and started looking at them through practical problems.
In this guide, I will walk you through how Python loops work, the difference between for and while, how control keywords like break and continue alter execution, and why enumerate() is a cleaner alternative to manual counters. To make this practical, I'll share real snippets from small projects I built while wrapping my head around these concepts.
The Two Core Loops in Python
Python gives us two primary tools for repetition: for loops and while loops. The distinction comes down to one question: Do you know how many times you need to run, or are you waiting for a condition to change?
1. The for Loop: Definite Iteration
A for loop moves through an iterable: like a list, a string, a tuple, or a range of numbers, one item at a time. It executes the code block for each element and stops automatically when it reaches the end.
names = ["Alice", "Bob", "Charlie"]
for name in names:
print(f"Hello, {name}!")
Here, Python handles the bookkeeping. It grabs "Alice", runs the block, grabs "Bob", and finishes after "Charlie". You don't have to check list lengths or manage indices manually.
2. The while Loop: Indefinite Iteration
A while loop runs as long as a specified condition evaluates to True. Because you often do not know in advance how many iterations you will need, it works well for event loops, game loops, or user input validation.
attempts = 3
while attempts > 0:
print(f"You have {attempts} attempts left.")
attempts -= 1
If the condition never becomes False, the loop runs forever. That is why every while loop needs either state changes within its body or an explicit exit strategy.
Steering Loop Execution: break and continue
Loops normally run on autopilot, but real-world logic often demands overrides. Python provides two primary keywords to alter loop flow: break and continue.
break: Immediately halts the loop and jumps straight to the code outside it.continue: Skips the rest of the current iteration and jumps directly to the next cycle.
Let’s look at how both work in practice.
Project 1: User Validation Using a while Loop and break
A classic scenario for a while loop is taking input from a user. You cannot predict whether someone will provide a valid password on their first attempt or their tenth.
I built a mini password checker that runs continuously using while True, evaluates input rules, and calls break as soon as the criteria are met:
def check_password():
while True:
password = input("Enter password: ")
length_ok = len(password) >= 8
not_password = password.lower() != "password"
with_digit = any(char.isnumeric() for char in password)
if length_ok and not_password and with_digit:
print("Password accepted.")
break
else:
print("Password rejected. Try again.")
if not length_ok:
print("Password must be at least 8 characters long.")
elif not not_password:
print("Password cannot be 'password'.")
elif not with_digit:
print("Password must contain at least 1 digit.")
check_password()
Why this works
Setting while True creates an intentional infinite loop. The program repeatedly prompts the user until every boolean condition evaluates to True. Once the input satisfies length_ok, not_password, and with_digit, the break statement fires. That immediately terminates the loop without needing an external flag variable.
Project 2: Data Filtering Using a for Loop and continue
While break bails out entirely, continue acts like a skip button. It is particularly useful when processing records where certain items should be ignored without stopping the whole workflow.
Here is a transaction ledger script where I needed to calculate total net deposits and withdrawals while filtering out administrative service fees:
transactions = [
('Deposit', 5000),
('Withdrawal', -1200),
('Deposit', 3000),
('Fee', -50),
('Deposit', 2000)
]
total = 0
for transaction_type, amount in transactions:
if transaction_type == 'Fee':
continue # Skip this iteration entirely
total += amount
print(f"{transaction_type}: {amount}")
print(f"The total transacted: {total}")
Why continue is useful here
When the loop encounters ('Fee', -50), the condition triggers continue. Python skips both total += amount and the print() statement below it, jumping immediately to the next tuple ('Deposit', 2000).
Without continue, you would need to wrap the calculation in nested if/else blocks. Using continue keeps your primary business logic unindented and easier to read.
Project 3: Clean Tracking with enumerate()
A common beginner habit when needing item positions is manually tracking an index counter:
# The cluttered way
items = ["Apples", "Bananas", "Cherries"]
index = 0
for item in items:
print(f"{index}: {item}")
index += 1
Or worse, looping over range(len(items)):
# The clunky way
for i in range(len(items)):
print(f"{i}: {items[i]}")
Python provides enumerate() to solve this cleanly. It wraps any iterable and yields pairs containing the current count along with the item itself.
Here is a mini task checklist script demonstrating how clean this looks in a project context:
tasks = [
"Review pull requests",
"Fix database migration bug",
"Update API documentation",
"Send release notes"
]
print("Today's Priority Queue:")
for priority, task in enumerate(tasks, start=1):
print(f"[{priority}] {task}")
Output:
Today's Priority Queue:
[1] Review pull requests
[2] Fix database migration bug
[3] Update API documentation
[4] Send release notes
Notice the start=1 argument. By default, enumerate() starts counting at 0, which matches Python's zero-based indexing. Passing start=1 instantly adapts the counter for human-facing output without needing clumsy math like priority + 1 inside your display strings.
Common Mistakes to Watch For
Forgetting to advance a counter in
whileloops: If you use a variable in your condition (likewhile count < 5:), make sure you updatecountinside the loop body. Forgetting this creates an infinite loop that pins your CPU.Modifying a list while looping over it: Removing or adding elements to a list you are currently iterating through causes skipped items and unpredictable behavior. If you need to filter a list, iterate over a copy or build a new list instead.
Overusing
range(len(...)): If you only need the items, usefor item in collection:. If you need both the index and the item, useenumerate(collection). Reaching forrange(len(...))is rarely the most readable choice in Python.
Summary Checklist
Use a
forloop when you have a sequence to traverse or know the number of iterations upfront.Use a
whileloop when iterating based on a state or condition that changes dynamically during execution.Use
breakto exit a loop immediately when a stopping condition is met.Use
continueto skip the rest of the current iteration and move to the next item.Use
enumerate()whenever you need item indices alongside their values.
Write small scripts to experiment with loop behavior. Once you can predict how data moves through each cycle, structuring your programs becomes straightforward.
Top comments (0)