THINK IN PYTHON
From Zero to Job-Ready Developer
MODULE 1 — CHAPTER 3
Loops: Teaching Python to Repeat Without
Losing Its Mind
Repetition is not laziness. It is the superpower of machines.
This chapter teaches you to wield that superpower.
CHAPTER 3
Loops: Teaching Python to Repeat Without
Losing Its Mind
PART 1 — OPENING STORY
The Night Thanos Needed a Loop
Thanos has the Infinity Gauntlet. Six stones to collect, six planets to conquer, a universe to balance.
Imagine if he wrote his plan without loops:
Thanos without loops — the painful way
defeat_enemy('Asgard')
defeat_enemy('Xandar')
defeat_enemy('Knowhere')
defeat_enemy('Titan')
defeat_enemy('Wakanda')
defeat_enemy('Earth')
collect_stone('Space Stone')
collect_stone('Mind Stone')
collect_stone('Reality Stone')
collect_stone('Power Stone')
collect_stone('Time Stone')
collect_stone('Soul Stone')
# 12 lines for 12 actions. Fine.
# But what about 12 BILLION souls to snap?
# You can't write a line for every one.
That's the problem loops solve. When an operation repeats — over a collection, over a condition, over
time — you don't write a line for each repetition. You define the operation ONCE and let Python repeat
it.
Thanos with a loop — the right way
stones = ['Space','Mind','Reality','Power','Time','Soul']
planets = ['Asgard','Xandar','Knowhere','Titan','Wakanda','Earth']
for planet in planets:
defeat_enemy(planet)
for stone in stones:
collect_stone(stone + ' Stone')
print('Perfectly balanced, as all things should be.')
# 8 lines. Handles 6 items today, 6 million tomorrow.
"A loop does in one line what copy-paste does in a thousand. And unlike
copy-paste, it never makes typos, never gets tired, and scales to a billion
without complaint."
— Senior Developer Rule #1
By the end of this chapter you will write loops that process entire databases, drive menu systems,
generate reports, automate batch tasks, and solve interview problems that stump most candidates. You
will understand the while loop, for loop, nested loops, break, continue, pass, enumerate, zip, list
comprehensions, and — most importantly — the loop design thinking that separates professionals from
beginners.
PART 2 — WHY LOOPS EXIST
Why Loops Exist: The Problem They Solve
Before loops were invented in programming languages, programmers literally had to write every
instruction by hand — one line per operation. If you wanted to process 1,000 records, you wrote 1,000
lines of code.
Loops changed everything. They let a computer do what computers are fundamentally better at than
humans: doing the same precise operation, over and over, without boredom, without mistakes, without
rest.
Real-World Loops Running Right Now — This Second
NETFLIX — Loops through 230M+ user profiles to generate recommendations every night
SWIGGY — Loops through nearby restaurants every second to update delivery estimates
INSTAGRAM — Loops through your follow list to rank your feed by relevance score
BANKS — Loops through 50M+ transactions daily for real-time fraud detection
GOOGLE — Loops through 8.5 billion daily searches to index and rank results
WHATSAPP — Loops through message queues to deliver to offline users when they
reconnect
YOUR PHONE — Loops exactly 60 times per second to refresh your screen display
ADYA TECH — Loops through student records, attendance sheets, trainer payments
monthly
Every single one of those systems uses the exact same loop concepts you're about to learn. The
syntax is simple. The power is unlimited.
PART 3 — REAL LIFE ANALOGY
Real Life Analogy: The Factory Assembly Line
Picture the Tata Motors factory in Pune. A thousand cars roll off the assembly line every day. At each
station, workers perform the same operation on every car that passes through.
• Station 1: Weld the chassis. Performed on Car #1, Car #2, Car #3 ... Car #1000.
• Station 2: Fit the engine. Same process. Every car.
• Station 3: Paint the body. Same process. Every car.
• Station 4: Quality check. Same process. Every car.
The factory doesn't write a new instruction manual for every single car. It defines the operation ONCE,
and the assembly line repeats it for every car that comes through.
A loop is your assembly line. You define the operation once. Python performs it for every item in your
collection — or for as long as a condition holds.
"Don't Repeat Yourself." This is called the DRY principle — the single
most important rule in all of software engineering. Loops are the primary
tool for following it.
— DRY: Don't Repeat Yourself — Andy Hunt & Dave Thomas, The Pragmatic Programmer
The Rocky Training Montage Analogy
In every Rocky film there is a training montage. Rocky doesn't punch a bag once and declare himself
ready. He runs the steps until his fitness reaches the target. He punches until his technique is perfect.
He keeps going UNTIL a condition is met.
That is a while loop. You don't know how many repetitions it will take. You just keep going until the goal
is achieved.
Rocky's training as Python
fitness = 40
target = 100
while fitness < target:
print(f'Training... current fitness: {fitness}')
fitness += 8 # Each session improves fitness
print(f'Rocky is ready! Final fitness: {fitness}')
# Loop runs until fitness >= 100. Rocky fights.
PART 4 — MOVIE ANALOGY
Movie Analogies: Loops Everywhere in Cinema
KGF Chapter 2 — Rocky Bhai's War
In KGF, Rocky Bhai doesn't defeat one enemy and go home. He fights wave after wave of Adheera's
soldiers. Each wave is one iteration of the loop. The loop runs while enemies remain.
KGF as a while loop
enemy_waves = 847
while enemy_waves > 0:
fight_wave()
enemy_waves -= 1
print('Rocky rules the gold mines.')
John Wick — The Continental Sequence
John Wick fights 77 enemies in the Continental. Same precision, same method, every single target.
That's a for loop — iterating over a collection of enemies, applying the same operation to each.
John Wick as a for loop
enemies = get_all_enemies_in_continental()
for enemy in enemies:
neutralize(enemy, style='precise')
print('John Wick completes his task.')
Baahubali — Building the Army
Baahubali's army builds siege equipment by every soldier performing the same task repeatedly.
Thousands of soldiers, same operation. A massive parallel loop — distributed computing in the ancient
world.
Pushpa — The Smuggling Run
Pushpa smuggles sandalwood load after load. Same route, same operation, repeated. Classic while
loop — keep running until the police checkpoint (break condition) stops you.
Vikram — The Investigation
Agent Amar investigates clue after clue, repeatedly checking each one until the truth is found. A for
loop over clues — with a break when the case is solved.
Money Heist — The Mint Operation
The Professor's team repeats the printing operation continuously. Same machine settings, same paper,
same ink — loop runs while the timer is active. A timed while loop.
PART 5 — THE while LOOP
The while Loop: Keep Going Until It's Done
The while loop is Python's most fundamental repetition tool. It runs a block of code again and again as
long as a condition remains True. It does not know in advance how many times it will run — it just
checks the condition before each iteration and stops when it becomes False.
Think of it as a security guard at the entrance of a building. Before letting each person in, the guard
checks the condition. As long as the condition is satisfied, people keep entering. The moment the
condition fails, the door closes.
Syntax and Structure
while loop — complete anatomy
# ┌─ keyword
# │ ┌─ condition (any expression that evaluates True/False)
# │ │ ┌─ colon is mandatory
while condition: #
# indented block — runs repeatedly while condition is True
body_of_loop
update_step # CRITICAL: must eventually make condition False
# Execution resumes here when condition becomes False
code_after_loop
Step-by-Step Execution Trace
Understanding exactly how Python executes a while loop prevents 90% of while loop bugs.
Execution trace — count from 1 to 5
count = 1
while count <= 5:
print(count)
count += 1
print('Loop finished')
# TRACE:
# Start: count=1. Check: 1<=5 TRUE. Print 1. count becomes 2.
# Round: count=2. Check: 2<=5 TRUE. Print 2. count becomes 3.
# Round: count=3. Check: 3<=5 TRUE. Print 3. count becomes 4.
# Round: count=4. Check: 4<=5 TRUE. Print 4. count becomes 5.
# Round: count=5. Check: 5<=5 TRUE. Print 5. count becomes 6.
# Round: count=6. Check: 6<=5 FALSE. Exit loop.
# Prints: 'Loop finished'
THE INFINITE LOOP TRAP — The Most Common Beginner Disaster
If nothing inside the loop moves the condition toward False, the loop runs forever.
Your program freezes. CPU hits 100%. Nothing responds.
Press Ctrl+C to kill an infinite loop.
INFINITE LOOP EXAMPLES:
count = 1
while count <= 5:
print(count)
# FORGOT count += 1 <-- loops forever at count=1
while True: # intentional — but needs a break inside
print('forever') # no break = genuinely infinite
DIAGNOSIS: Before writing any while loop, ask yourself two questions:
1. What value will eventually make my condition False?
2. Does my loop body move toward that value every iteration?
If you cannot answer both, your loop is dangerous.
Beginner Example 1: Rocket Countdown
rocket_launch.py
# Classic beginner while loop — countdown timer
count = 10
print('=== ISRO ROCKET LAUNCH SEQUENCE ===')
while count > 0:
print(f'T-minus {count} seconds...')
count -= 1
print('IGNITION!')
print('Rocket launched! Chandrayaan is on its way.')
Beginner Example 2: Simple Number Accumulator
[Link]
# Add numbers until user enters 0
total = 0
count = 0
print('Enter numbers to add. Enter 0 to stop.')
num = int(input('Enter number: '))
while num != 0:
total += num
count += 1
num = int(input('Enter number: '))
if count > 0:
print(f'Sum of {count} numbers: {total}')
print(f'Average: {total / count:.2f}')
else:
print('No numbers were entered.')
Intermediate Example: PIN Validator with Lockout
pin_validator.py
# Security pattern used in ATMs and banking apps
CORRECT_PIN = '7842'
MAX_ATTEMPTS = 3
attempts = 0
locked = False
while attempts < MAX_ATTEMPTS:
pin = input(f'Enter PIN (attempt {attempts+1}/{MAX_ATTEMPTS}): ')
attempts += 1
if pin == CORRECT_PIN:
print('Access granted. Welcome!')
break
else:
remaining = MAX_ATTEMPTS - attempts
if remaining > 0:
print(f'Incorrect PIN. {remaining} attempt(s) remaining.')
else:
locked = True
print('Account LOCKED. Contact your bank.')
# Check if we exited because of success or failure
if not locked and pin != CORRECT_PIN:
pass # covered above
Intermediate Example: Number Guessing Game
guessing_game.py
import random
secret_number = [Link](1, 100)
attempts = 0
max_attempts = 7
won = False
print('=== NUMBER GUESSING GAME ===')
print(f'Guess a number between 1 and 100.')
print(f'You have {max_attempts} attempts. Good luck!')
print()
while attempts < max_attempts:
guess = int(input(f'Attempt {attempts+1}: '))
attempts += 1
if guess == secret_number:
print(f'CORRECT! You guessed it in {attempts} attempt(s)!')
if attempts == 1:
print('Incredible! First try!')
elif attempts <= 3:
print('Excellent! Very fast!')
else:
print('Well done!')
won = True
break
elif guess < secret_number:
diff = secret_number - guess
if diff > 30: hint = 'Way too low!'
elif diff > 10: hint = 'Too low!'
else: hint = 'Just a little higher!'
print(hint)
else:
diff = guess - secret_number
if diff > 30: hint = 'Way too high!'
elif diff > 10: hint = 'Too high!'
else: hint = 'Just a little lower!'
print(hint)
if not won:
print(f'Out of attempts! The number was {secret_number}.')
Professional Pattern: while True with break (Input Validation)
This is the most commonly used while loop pattern in production code. Use it whenever you need to
keep asking until you get valid input.
Input validation — professional pattern
# Pattern: while True + break when valid
# Used in every CLI tool, ATM, menu system
def get_valid_age():
while True:
try:
age = int(input('Enter age (1-120): '))
if 1 <= age <= 120:
return age
print('Age must be between 1 and 120.')
except ValueError:
print('Please enter a valid number.')
def get_valid_choice(options):
while True:
choice = input(f'Enter choice {options}: ').strip()
if choice in options:
return choice
print(f'Invalid choice. Please enter one of: {options}')
# Usage
age = get_valid_age()
mode = get_valid_choice(['1','2','3','4'])
print(f'Age: {age}, Mode: {mode}')
Professional Pattern: Menu-Driven Application
student_management_menu.py
# Architecture used in ATMs, POS systems, admin panels
students = []
def show_menu():
print('\n' + '='*40)
print(' ADYA TECHNOLOGY — STUDENT PORTAL')
print('='*40)
print(' 1. Enrol New Student')
print(' 2. View All Students')
print(' 3. Search Student')
print(' 4. Class Statistics')
print(' 5. Exit')
print('='*40)
running = True
while running:
show_menu()
choice = input('Select option: ').strip()
if choice == '1':
name = input('Student name: ').strip().title()
course = input('Course enrolled: ').strip()
marks = int(input('Entry test marks (0-100): '))
[Link]({'name':name,'course':course,'marks':marks})
print(f'{name} enrolled successfully!')
elif choice == '2':
if not students:
print('No students enrolled yet.')
else:
print(f'\n{"#":<3} {"Name":<20} {"Course":<20}
{"Marks":>5}')
print('-'*50)
for i,s in enumerate(students,1):
print(f'{i:<3} {s["name"]:<20} {s["course"]:<20}
{s["marks"]:>5}')
elif choice == '3':
query = input('Search by name: ').strip().lower()
results = [s for s in students if query in s['name'].lower()]
if results:
for s in results:
print(f'Found: {s["name"]} | {s["course"]} | Marks:
{s["marks"]}')
else:
print('No student found.')
elif choice == '4':
if students:
avg = sum(s['marks'] for s in students)/len(students)
top = max(students, key=lambda s: s['marks'])
print(f'Total students : {len(students)}')
print(f'Class average : {avg:.1f}')
print(f'Top student : {top["name"]} ({top["marks"]}
marks)')
else:
print('No data available.')
elif choice == '5':
print('Thank you. Goodbye!')
running = False
else:
print('Invalid option. Please enter 1-5.')
The while-else Clause: Python's Unique Feature
Python is the only major language that lets you attach an else to a while loop. The else block runs
ONLY if the loop completed normally — that is, the condition became False naturally, not because of a
break.
while-else
# Use case: search with a clear 'not found' outcome
suspects = ['Rajesh', 'Priya', 'Karan', 'Arun', 'Sonal']
target = 'Karan'
i = 0
while i < len(suspects):
if suspects[i] == target:
print(f'Found {target} at position {i}!')
break
i += 1
else:
# Only runs if no break was hit
print(f'{target} is not in the list.')
# Cleaner than using a boolean 'found' flag.
# Interviewers ask about this — most candidates have never heard of
it.
PART 6 — THE for LOOP
The for Loop: The Most Used Loop in Python
If while is 'keep going until done,' the for loop is 'go through every single item in this collection.'
The for loop is the workhorse of Python programming. Data science, web development, automation, file
processing — almost all of it is for loops. When you have a known collection of things and you want to
do something to each one, you use a for loop.
Syntax
for loop — anatomy
# ┌─ keyword
# │ ┌─ loop variable (takes value of each item)
# │ │ ┌─ keyword
# │ │ │ ┌─ any iterable (list,str,dict,range,tuple...)
for item in collection:
# body runs once for each item in collection
# 'item' holds the current value each round
Iterating Over a List
for loop with a list
avengers = ['Iron Man','Thor','Hulk','Black Widow','Captain
America','Hawkeye']
print('Avengers Roll Call:')
for hero in avengers:
print(f' {hero} — READY!')
# Python picks each hero one by one, runs the body, moves to next.
# You never see the index. You just see the value.
# Find specific hero
for hero in avengers:
if 'Iron' in hero:
print(f'Found the team leader: {hero}')
The range() Function — Your Essential Tool
range() generates a sequence of numbers on demand. It's memory-efficient (doesn't store all numbers),
and it's used whenever you need to repeat something a fixed number of times.
range() — all three forms
# FORM 1: range(stop) — starts at 0
for i in range(5):
print(i, end=' ') # 0 1 2 3 4
print()
# FORM 2: range(start, stop) — includes start, excludes stop
for i in range(1, 6):
print(i, end=' ') # 1 2 3 4 5
print()
# FORM 3: range(start, stop, step)
for i in range(0, 20, 4):
print(i, end=' ') # 0 4 8 12 16
print()
# Counting DOWN
for i in range(10, 0, -1):
print(i, end=' ') # 10 9 8 7 6 5 4 3 2 1
print()
# Memory note: range(10_000_000) uses almost no RAM
# list(range(10_000_000)) uses ~80MB — avoid that
Iterating Over a String — Strings are Iterable
for loop over a string
# Every character is an item
message = 'PYTHON'
for char in message:
print(char, end='-') # P-Y-T-H-O-N-
print()
# Count vowels
word = 'programming'
vowels = 0
for char in word:
if char in 'aeiouAEIOU':
vowels += 1
print(f'Vowels in "{word}": {vowels}') # 3
# Reverse a string character by character
word = 'Python'
reversed_word = ''
for char in word:
reversed_word = char + reversed_word
print(reversed_word) # nohtyP
Iterating Over a Dictionary
for loop over a dictionary
student = {'name':'Suraj','age':24,'course':'Python','marks':92}
# Iterate over keys (default)
for key in student:
print(key)
# Iterate over values
for value in [Link]():
print(value)
# Iterate over key-value pairs (most common)
for key, value in [Link]():
print(f'{key:10}: {value}')
# Real use: display a profile
print('\n=== STUDENT PROFILE ===')
for field, data in [Link]():
print(f'{[Link]():<10}: {data}')
enumerate() — Index + Value Together
One of the most useful Python built-ins. When you need both the position and the value, use
enumerate() — never range(len(list)).
enumerate() — the Pythonic way
subjects = ['Python','Data Science','Machine Learning','Web
Dev','Cloud']
# WRONG — old-school, error-prone
for i in range(len(subjects)):
print(f'{i+1}. {subjects[i]}')
# RIGHT — Pythonic, clean, safe
for i, subject in enumerate(subjects, start=1):
print(f'{i}. {subject}')
# Output:
# 1. Python
# 2. Data Science
# 3. Machine Learning
# 4. Web Dev
# 5. Cloud
# Real use: numbered menu display
print('\nSelect a course:')
for i, sub in enumerate(subjects, 1):
print(f' [{i}] {sub}')
zip() — Loop Over Multiple Lists at Once
zip() — parallel iteration
students = ['Suraj', 'Priya', 'Rahul', 'Anita']
scores = [92, 78, 96, 65]
courses = ['Python', 'Excel', 'ML', 'Web']
# Pairs them up — like a zipper
for student, score, course in zip(students, scores, courses):
status = 'PASS' if score >= 50 else 'FAIL'
print(f'{student:<10} | {course:<8} | {score:>3} | {status}')
# zip stops at the SHORTEST list — important to know
# Create a dictionary from two lists using zip
names = ['Iron Man', 'Thor', 'Hulk']
powers = [85, 92, 99]
power_dict = dict(zip(names, powers))
print(power_dict)
# {'Iron Man': 85, 'Thor': 92, 'Hulk': 99}
for-else: Python's Secret Loop Feature
Just like while-else, a for loop can have an else clause. The else runs ONLY if the loop ran to
completion without hitting a break.
for-else
# Classic use case: search with 'not found' handling
products = ['Laptop', 'Keyboard', 'Monitor', 'Mouse', 'Webcam']
search = 'Tablet'
for product in products:
if product == search:
print(f'Product found: {product}')
break
else:
# Runs only if no break occurred
print(f'"{search}" is not available in our inventory.')
# This is cleaner than the 'found' boolean flag pattern:
# found = False
# for product in products:
# if product == search:
# found = True
# break
# if not found:
# print('Not found')
PART 7 — NESTED LOOPS
Nested Loops: Loops Inside Loops
A nested loop is a loop inside another loop. The inner loop runs COMPLETELY — every single iteration
— for every single iteration of the outer loop.
This is the clock analogy: the minute hand (inner loop) completes a full revolution for every single tick of
the hour hand (outer loop). The hour hand is the outer loop. The minute hand is the inner loop.
Execution Model — How it Actually Works
Nested loop execution trace
# Outer: 3 iterations. Inner: 3 iterations.
# Total body executions: 3 x 3 = 9
for outer in range(1, 4):
for inner in range(1, 4):
print(f'outer={outer}, inner={inner}')
print('--- inner loop complete ---')
# Output:
# outer=1, inner=1
# outer=1, inner=2
# outer=1, inner=3
# --- inner loop complete ---
# outer=2, inner=1 <-- outer increments, inner RESTARTS
# outer=2, inner=2
# outer=2, inner=3
# --- inner loop complete ---
# outer=3, inner=1
# outer=3, inner=2
# outer=3, inner=3
# --- inner loop complete ---
Classic: Multiplication Table
multiplication_table.py
print('MULTIPLICATION TABLE')
print(' ' + ' '.join(f'{j:3}' for j in range(1,11)))
print(' ' + '-'*35)
for i in range(1, 11):
row = f'{i:2} |'
for j in range(1, 11):
row += f'{i*j:4}'
print(row)
Pattern Printing — Interview Favourite
Pattern problems using nested loops appear in almost every Python interview. Master all of these.
Essential patterns
n = 5
# PATTERN 1: Right-angled triangle
print('Pattern 1:')
for i in range(1, n+1):
print('* ' * i)
# PATTERN 2: Inverted triangle
print('Pattern 2:')
for i in range(n, 0, -1):
print('* ' * i)
# PATTERN 3: Pyramid (centered)
print('Pattern 3:')
for i in range(1, n+1):
print(' '*(n-i) + '* '*i)
# PATTERN 4: Number triangle
print('Pattern 4:')
for i in range(1, n+1):
for j in range(1, i+1):
print(j, end=' ')
print()
# PATTERN 5: Floyd's triangle
print('Pattern 5:')
num = 1
for i in range(1, n+1):
for j in range(i):
print(num, end=' ')
num += 1
print()
# PATTERN 6: Diamond
print('Pattern 6:')
for i in range(1, n+1):
print(' '*(n-i) + '* '*i)
for i in range(n-1, 0, -1):
print(' '*(n-i) + '* '*i)
Real World: Batch Report Generator
batch_report.py
# Training institute quarterly report
batches = {
'Batch A (Python)': [85, 92, 78, 96, 73, 88, 91],
'Batch B (Excel)' : [72, 68, 75, 80, 70, 65, 77],
'Batch C (ML)' : [95, 98, 92, 96, 99, 94, 97],
}
print('=== ADYA TECHNOLOGY — BATCH PERFORMANCE REPORT ===')
print()
overall_scores = []
for batch_name, scores in [Link]():
avg = sum(scores) / len(scores)
passed = sum(1 for s in scores if s >= 50)
failed = len(scores) - passed
highest = max(scores)
lowest = min(scores)
overall_scores.extend(scores)
print(f'Batch : {batch_name}')
print(f'Students : {len(scores)}')
print(f'Average : {avg:.1f}%')
print(f'Highest : {highest}% Lowest: {lowest}%')
print(f'Passed : {passed} Failed: {failed}')
# Grade distribution using nested loop logic
grade_counts = {'A+':0,'A':0,'B':0,'C':0,'F':0}
for s in scores:
if s>=90: grade_counts['A+']+=1
elif s>=80: grade_counts['A']+=1
elif s>=70: grade_counts['B']+=1
elif s>=50: grade_counts['C']+=1
else: grade_counts['F']+=1
grade_str = ' '.join(f'{g}:{c}' for g,c in grade_counts.items()
if c>0)
print(f'Grades : {grade_str}')
print('-'*50)
overall_avg = sum(overall_scores)/len(overall_scores)
print(f'INSTITUTE AVERAGE: {overall_avg:.1f}%')
Nested Loop Performance — Know This for Interviews
COMPLEXITY: N items in outer loop x N items in inner = N*N = O(n^2) operations.
O(n^2) is EXPONENTIAL growth. For n=1000: 1,000,000 operations.
For n=1,000,000: one TRILLION operations. Unusable.
RULE: Before writing a nested loop, ask: 'Can I solve this with one loop?'
Senior developers always challenge O(n^2) solutions and look for O(n) alternatives.
Example: Finding duplicates in a list.
O(n^2): nested loops checking each pair
O(n): one loop building a set/dict, checking membership
We'll revisit this in the Algorithms chapter. For now: know it's important.
PART 8 — break, continue, AND pass
Loop Control Statements: break, continue, and pass
Three keywords that give you surgical precision over your loops. Every professional Python developer
uses all three constantly. They are not optional — they are essential.
break — Emergency Exit
break immediately terminates the entire loop. Python jumps to the code after the loop. No more
iterations happen.
Real-world analogy: A fire alarm in a factory. The moment it sounds, EVERYONE stops work and exits.
No one finishes their current task. Immediate exit.
break — search and stop
# The most common use of break: stop when you find what you need
inventory = [
('Laptop', True, 45999),
('Keyboard', True, 2499),
('Tablet', False, 35999),
('Monitor', True, 18999),
('Webcam', True, 3499),
]
search = 'Tablet'
print(f'Searching for: {search}')
for product, in_stock, price in inventory:
print(f' Checking {product}...')
if product == search:
if in_stock:
print(f' Found! {product} is available at Rs {price:,}')
else:
print(f' Found! {product} is OUT OF STOCK.')
break # Stop searching — we found it
else:
print(f' {search} not in inventory.')
# Efficiency: we stop as soon as we find the item.
# No point checking Monitor and Webcam after finding Tablet.
break with while True — the professional validation pattern
# while True + break = 'run forever until valid input'
# This pattern is everywhere in professional code
while True:
user_input = input('Enter a positive number: ').strip()
if not user_input.isdigit():
print('Error: Please enter digits only.')
continue # Go back and ask again
number = int(user_input)
if number <= 0:
print('Error: Number must be positive.')
continue # Go back and ask again
break # Valid input received — exit the validation loop
print(f'You entered: {number}')
# This loop runs until the user gives a valid positive integer.
# Robust. Professional. Used everywhere.
continue — Skip and Move On
continue skips the rest of the current iteration and jumps straight to the next one. The loop does NOT
stop — it just skips this round and continues with the next item.
Real-world analogy: A quality inspector on a production line. If an item is defective, skip it and move to
the next. Don't stop the entire line — just this one item is rejected.
continue — skip defective items
# Process valid records, skip invalid ones
raw_data = [45, None, 78, -5, 92, 0, None, 55, 88, -12, 73]
valid_scores = []
skipped = 0
for score in raw_data:
# Skip None values (missing data)
if score is None:
skipped += 1
continue
# Skip negative values (data error)
if score < 0:
skipped += 1
continue
# Skip zeros (absent/not graded)
if score == 0:
skipped += 1
continue
# Only valid scores reach here
valid_scores.append(score)
print(f'Valid scores : {valid_scores}')
print(f'Skipped : {skipped} records')
print(f'Average (valid): {sum(valid_scores)/len(valid_scores):.1f}')
continue — real world: email batch sender
# Used in marketing platforms — skip unsubscribed/invalid
email_list = [
{'email': 'suraj@[Link]', 'subscribed': True, 'valid': True},
{'email': 'priya@[Link]', 'subscribed': False, 'valid': True},
{'email': 'invalid-email', 'subscribed': True, 'valid':
False},
{'email': 'rahul@[Link]', 'subscribed': True, 'valid': True},
{'email': 'anita@[Link]', 'subscribed': True, 'valid': True},
]
sent = 0
skipped = 0
for contact in email_list:
if not contact['valid']:
print(f'SKIP (invalid): {contact["email"]}')
skipped += 1
continue
if not contact['subscribed']:
print(f'SKIP (unsubscribed): {contact["email"]}')
skipped += 1
continue
# Reaches here only for valid + subscribed
print(f'SENT: {contact["email"]}')
sent += 1
print(f'\nSent: {sent} | Skipped: {skipped}')
pass — The Intentional Do-Nothing
pass is a null operation — it does absolutely nothing. Python requires that code blocks are not empty.
When you need an empty block (a skeleton, a placeholder, or a deliberate no-op), you use pass.
pass — legitimate uses
# USE 1: Placeholder while building structure
def calculate_gst(amount):
pass # TODO: implement next sprint
def send_notification(user):
pass # TODO: integrate notification service
# USE 2: Empty exception handler (suppress specific errors)
for filename in ['[Link]', '[Link]', '[Link]']:
try:
with open(filename) as f:
process(f)
except FileNotFoundError:
pass # Intentionally ignore missing files
# USE 3: Skeleton class
class PaymentGateway:
pass # Will add methods later
# USE 4: Conditional no-op
for item in items:
if item.is_archived:
pass # Archived items: do nothing intentionally
else:
process(item)
# WRONG use: pass where you meant to write real code
# If you find pass in production code with no TODO comment,
# it's probably a bug waiting to happen.
break vs continue vs pass — Quick When to use each
Reference break: when goal is reached,
break: critical error found,
Exits entire loop user chose exit,
No more iterations target item found.
Only inner loop exits
continue: when item is invalid,
continue: should be skipped,
Skips THIS iteration condition not met for
Loop continues normally this item only.
Jumps to next item
pass: skeleton code,
pass: future implementation,
Does nothing at all suppress specific errors,
Placeholder only intentional no-op.
Loop is unaffected
PART 9 — LOOP DESIGN THINKING
Loop Design Thinking: How Senior Developers Choose
Beginners ask: 'How do I write a loop?' Senior developers ask: 'Which loop is right for THIS problem,
and how do I write it cleanly?' Here is the decision framework used by experienced Python engineers.
The Loop Selection Decision Framework
STEP 1: What am I repeating?
→ Do I have a collection (list, dict, string, file lines)? → for loop
→ Am I waiting for something to happen? → while loop
→ Am I repeating exactly N times? → for i in range(N)
STEP 2: Do I know how many times upfront?
→ YES, fixed count → for loop with range()
→ NO, depends on data → for loop over collection
→ NO, depends on event → while loop
STEP 3: Do I need the loop variable (index)?
→ Need index AND value → enumerate()
→ Need index only → range(len())
→ Need value only → for item in collection
→ Need two lists together → zip()
STEP 4: Any early exit needed?
→ Stop when found → break
→ Skip invalid items → continue
→ Keep trying until valid → while True: + break
The Accumulator Pattern — Most Common Loop Pattern
The accumulator pattern is the foundation of all data processing loops. You initialize a container before
the loop, update it inside the loop, and read the final result after the loop ends.
All four accumulator patterns
monthly_sales = [145000,132000,178000,156000,189000,201000,
167000,143000,192000,215000,248000,267000]
# PATTERN 1: Sum accumulator
total = 0
for sale in monthly_sales:
total += sale
print(f'Annual total: Rs {total:,}')
# PATTERN 2: Count accumulator
above_target = 0
target = 180000
for sale in monthly_sales:
if sale >= target:
above_target += 1
print(f'Months above target: {above_target}/12')
# PATTERN 3: Max/Min tracker
best = monthly_sales[0]
worst = monthly_sales[0]
best_month = worst_month = 0
for i, sale in enumerate(monthly_sales):
if sale > best:
best = sale
best_month = i + 1
if sale < worst:
worst = sale
worst_month = i + 1
print(f'Best month: #{best_month} — Rs {best:,}')
print(f'Worst month: #{worst_month} — Rs {worst:,}')
# PATTERN 4: List builder (collect filtered results)
strong_months = []
for i, sale in enumerate(monthly_sales, 1):
if sale >= 200000:
strong_months.append(i)
print(f'Months with Rs 2L+ sales: {strong_months}')
List Comprehensions: The Most Pythonic Loop
List comprehensions are Python's signature feature. They create a new list from an existing collection
in a single, readable line. They are faster than manual for loops because Python optimizes them
internally.
Every professional Python developer uses list comprehensions constantly. Every Python interviewer
tests them.
List comprehension — from beginner to pro
# STRUCTURE: [expression for item in iterable if condition]
# what to add ^ ^name ^ ^source ^ ^filter
numbers = list(range(1, 21))
# MANUAL for loop
squares = []
for n in numbers:
[Link](n ** 2)
# COMPREHENSION — same result, one line
squares = [n**2 for n in numbers]
# WITH FILTER — only even squares
even_squares = [n**2 for n in numbers if n % 2 == 0]
print(even_squares) # [4,16,36,64,100,144,196,256,324,400]
# STRING PROCESSING — clean a list of names
raw_names = [' tony ', ' BRUCE ', ' peter ', ' NATASHA ']
clean_names = [[Link]().title() for name in raw_names]
print(clean_names) # ['Tony', 'Bruce', 'Peter', 'Natasha']
# FILTERING — only passing grades
all_scores = [85, 42, 91, 38, 76, 55, 62, 49, 88]
passing = [s for s in all_scores if s >= 50]
failing = [s for s in all_scores if s < 50]
# TRANSFORMATION — convert to grade labels
grades = ['A+' if s>=90 else 'A' if s>=80 else 'B' if s>=70
else 'C' if s>=50 else 'F' for s in all_scores]
print(grades) # ['A', 'F', 'A+', 'F', 'B', 'C', 'C', 'F', 'A']
Generator Expressions — For Large Data
When processing millions of items, a list comprehension loads everything into memory at once. A
generator expression processes one item at a time — almost zero memory overhead.
Generator vs list comprehension
# List comprehension — loads ALL into memory
squares_list = [x**2 for x in range(10_000_000)]
# Uses ~400MB of RAM
# Generator expression — computes on demand
squares_gen = (x**2 for x in range(10_000_000))
# Uses ~120 bytes of RAM
# Use generators with sum, max, any, all, min
total = sum(x**2 for x in range(10_000_000))
big = any(x > 9_999_990 for x in range(10_000_000))
# Rule: if you only need to ITERATE ONCE and don't need
# random access, use a generator (parentheses) not a list (brackets).
Pythonic Built-ins That Replace Manual Loops
A common interview trap: writing a 10-line loop for something Python does in one line. Know these
built-ins.
Replace loops with built-ins
scores = [85, 92, 78, 65, 91, 74, 88]
# DON'T write loops for these:
total = sum(scores)
highest = max(scores)
lowest = min(scores)
count = len(scores)
average = sum(scores) / len(scores)
sorted_s = sorted(scores)
reversed_s = sorted(scores, reverse=True)
# any() — is there AT LEAST ONE score above 90?
has_distinction = any(s >= 90 for s in scores) # True
# all() — did EVERYONE pass (>=50)?
all_passed = all(s >= 50 for s in scores) # True
# filter() — built-in functional filter
passing = list(filter(lambda s: s >= 50, scores))
# map() — apply function to every item
curved = list(map(lambda s: min(100, s+5), scores))
# sorted with key — sort students by score descending
students = [{'name':'Raj','score':78},{'name':'Priya','score':92}]
ranked = sorted(students, key=lambda s: s['score'], reverse=True)
PART 10 — COMMON MISTAKES & DEBUGGING
Common Mistakes: The Errors Every Beginner Makes
These are the exact mistakes your classmates will make. Learn them now. Fix them before the
interview.
Mistake 1: Off-By-One Error
Off-by-one — the classic bug
# GOAL: Print numbers 1 through 10
# WRONG: Stops at 9
for i in range(10):
print(i) # 0,1,2,...,9 — misses 10, starts from 0
# CORRECT:
for i in range(1, 11):
print(i) # 1,2,...,10
# WRONG: Misses last element
names = ['Alice', 'Bob', 'Carol']
for i in range(len(names) - 1): # stops at index 1!
print(names[i])
# CORRECT: Iterate directly
for name in names:
print(name)
Mistake 2: Modifying a List While Iterating It
Never mutate during iteration
# WRONG — unpredictable, skips elements
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
for num in numbers:
if num % 2 == 0:
[Link](num) # Changes list while iterating
print(numbers) # [1, 3, 5, 7] — looks right, but is unreliable
# WHY: When you remove an element, the list shifts left.
# The iterator skips the element that moved into the removed slot.
# CORRECT — iterate a copy, modify original
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
for num in numbers[:]: # [:] makes a copy
if num % 2 == 0:
[Link](num)
# BEST — list comprehension (clean, fast, safe)
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
numbers = [n for n in numbers if n % 2 != 0]
print(numbers) # [1, 3, 5, 7]
Mistake 3: Using range(len()) When You Don't Need It
range(len()) anti-pattern
heroes = ['Iron Man', 'Thor', 'Hulk', 'Captain America']
# WRONG (unnecessarily complex)
for i in range(len(heroes)):
print(heroes[i])
# CORRECT (when you only need values)
for hero in heroes:
print(hero)
# CORRECT (when you need index + value)
for i, hero in enumerate(heroes, start=1):
print(f'{i}. {hero}')
# RULE: range(len()) is only justified when you need to
# MODIFY elements by index. All other uses are wrong.
for i in range(len(heroes)):
heroes[i] = heroes[i].upper() # Justified: modifying by index
Mistake 4: Variable Reset Inside the Loop
Accumulator reset bug
# GOAL: Sum all numbers
numbers = [10, 20, 30, 40, 50]
# WRONG — total resets to 0 every iteration
for num in numbers:
total = 0 # BUG: inside the loop
total += num
print(total) # 50 (only last number, not sum)
# CORRECT — total is outside the loop
total = 0 # CORRECT: outside the loop
for num in numbers:
total += num
print(total) # 150
# RULE: Accumulators always initialize BEFORE the loop.
# If your variable is resetting unexpectedly, check its
# indentation — it may be inside the loop accidentally.
Mistake 5: break Only Exits the Innermost Loop
break scope in nested loops
# WRONG assumption: break exits all loops
for i in range(3):
for j in range(3):
if j == 1:
break # Only exits inner for-j loop!
print(f'Outer i={i} continues') # This STILL prints 3 times
# To exit both loops: use a flag
done = False
for i in range(3):
for j in range(3):
if i == 1 and j == 1:
done = True
break
if done:
break # Now outer also exits
# Or: refactor into a function and use return
def find_target(matrix):
for i, row in enumerate(matrix):
for j, val in enumerate(row):
if val == 99:
return i, j # exits EVERYTHING cleanly
return None, None
PART 11 — SENIOR DEVELOPER PERSPECTIVE
Senior Developer Perspective: Loop Craftsmanship
Junior developers write loops that work. Senior developers write loops that work, read cleanly, run
efficiently, and are easy to debug. Here is the difference.
Write Flat, Not Deep
Junior: Deep Nesting Senior: Flat and Readable
for dept in departments: from itertools import chain
for team in [Link]:
for emp in [Link]: all_emps = chain.from_iterable(
if [Link]: [Link]
if [Link] > for d in departments
50000: for t in [Link]
process(emp) )
eligible = (e for e in all_emps
if [Link] and
[Link]>50000)
for emp in eligible:
process(emp)
Extract Loop Bodies Into Functions
Extract for testability and readability
# JUNIOR: everything crammed in the loop
for student in students:
avg = sum(student['scores']) / len(student['scores'])
if avg >= 90: grade = 'A+'
elif avg >= 80: grade = 'A'
elif avg >= 70: grade = 'B'
elif avg >= 50: grade = 'C'
else: grade = 'F'
passed = avg >= 50
student['grade'] = grade
student['passed'] = passed
# 10 more lines...
# SENIOR: loop body in a named function
def evaluate_student(student):
avg = sum(student['scores']) / len(student['scores'])
student['average'] = round(avg, 1)
student['grade'] = get_grade(avg)
student['passed'] = avg >= 50
return student
def get_grade(avg):
if avg >= 90: return 'A+'
if avg >= 80: return 'A'
if avg >= 70: return 'B'
if avg >= 50: return 'C'
return 'F'
# Clean, testable, readable
processed = [evaluate_student(s) for s in students]
Use Dictionary and Set for O(n) Lookups
O(n^2) vs O(n) — the interview separator
# PROBLEM: Find students who appear in BOTH lists
batch_a = ['Suraj','Priya','Rahul','Anita','Kiran']
batch_b = ['Priya','Anita','Deepa','Suresh','Suraj']
# JUNIOR APPROACH: O(n^2) — nested loops
common = []
for student in batch_a:
for other in batch_b:
if student == other:
[Link](student)
print(common) # Works but O(n*m) time
# SENIOR APPROACH: O(n) — use set intersection
common = list(set(batch_a) & set(batch_b))
print(common) # Same result, much faster
# For N=10000 students:
# Junior: 100,000,000 comparisons
# Senior: ~20,000 operations
# 5000x faster — the difference between 0.1s and 8 minutes
PART 12 — INTERVIEW MODE
Interview Mode: What They Actually Ask
🎯 What Interviewers ❌ How Candidates Fail ✅ Senior Dev Answer
Ask • Writing range(len()) • for = known collection or
1. Difference: for vs when iterating directly count. while = condition-
while? • Not knowing break only based, unknown count.
2. What does break do exits innermost loop • break exits loop
vs continue? • Cannot explain for-else completely. continue
3. What is an infinite — most candidates have skips current round.
loop? Prevent it? never seen it pass does nothing.
4. What is • Writing verbose loops • Infinite loop: condition
enumerate()? Show instead of never False. Prevent:
me. sum()/any()/all() ensure body moves
toward termination.
5. What is a list • Not knowing list
comprehension? comprehensions • enumerate gives
index+value.
6. What does for-else • Modifying a list while
enumerate(lst,1) starts
do? iterating it
index at 1.
7. What is • Accumulator variable
• for-else: else runs only if
range(1,10,2)? reset inside the loop
no break hit. Replaces
8. Reverse a list with a • Cannot convert for loop the found-flag pattern.
loop. to list comprehension • List comprehension:
9. Print Fibonacci with [expr for x in iterable if
a loop. cond]. Faster, cleaner
10. Find the max than manual loop.
without max(). • Use set intersection
instead of nested loop
for O(n) vs O(n^2)
lookups.
PART 13 — CORPORATE EXAMPLES
Corporate Examples: Loops in Production Code
Corporate Example 1: Monthly Payroll Processor
payroll_processor.py
# Used in every HR/payroll system in India
employees = [
{'id':'E001','name':'Suraj Kumar',
'basic':35000,'days_worked':26,'leave_days':2},
{'id':'E002','name':'Priya Sharma',
'basic':42000,'days_worked':28,'leave_days':0},
{'id':'E003','name':'Rahul Singh',
'basic':28000,'days_worked':22,'leave_days':6},
{'id':'E004','name':'Anita Verma',
'basic':55000,'days_worked':28,'leave_days':0},
{'id':'E005','name':'Karthik Nair',
'basic':38000,'days_worked':25,'leave_days':3},
]
TOTAL_WORKING_DAYS = 28
PF_RATE = 0.12
ESI_RATE = 0.0175
PROF_TAX = 200
print(f'{'ID':<6}{'Name':<20}{'Basic':>8}{'Gross':>9}{'Deduct':>9}
{'Net':>9}')
print('='*63)
total_gross = total_net = total_deductions = 0
for emp in employees:
# Per-day salary calculation
per_day = emp['basic'] / TOTAL_WORKING_DAYS
gross = per_day * emp['days_worked']
# Standard deductions
pf = gross * PF_RATE
esi = gross * ESI_RATE if gross <= 21000 else 0
leave_ded = per_day * emp['leave_days'] if emp['leave_days'] > 2
else 0
total_ded = pf + esi + PROF_TAX + leave_ded
net_pay = gross - total_ded
total_gross += gross
total_net += net_pay
total_deductions += total_ded
print(f'{emp["id"]:<6}{emp["name"]:<20}{emp["basic"]:>8,}
{gross:>9,.0f}{total_ded:>9,.0f}{net_pay:>9,.0f}')
print('='*63)
print(f'{'TOTAL':<26}{total_gross:>9,.0f}{total_deductions:>9,.0f}
{total_net:>9,.0f}')
print(f'\nTotal Payroll Disbursement: Rs {total_net:,.2f}')
Corporate Example 2: Attendance Analyser
attendance_analyser.py
# Used in Adya Technology and every training institute
import random
# Simulate 30-day attendance for a batch
[Link](42)
students =
['Suraj','Priya','Rahul','Anita','Karthik','Deepa','Arjun','Sneha']
attendance = {
name: [[Link](['P','P','P','A']) for _ in range(30)]
for name in students
}
WORKING_DAYS = 30
MIN_ATTENDANCE = 75
print('=== BATCH ATTENDANCE REPORT ===')
print(f'{'Student':<12}{'Present':>8}{'Absent':>8}{'%':>7}{'Bar':<22}
{'Status'}')
print('-'*68)
eligible = []
ineligible = []
for student, records in [Link]():
present = [Link]('P')
absent = [Link]('A')
pct = (present / WORKING_DAYS) * 100
bar = '#' * int(pct/5) + '.' * (20 - int(pct/5))
status = 'ELIGIBLE' if pct >= MIN_ATTENDANCE else 'INELIGIBLE'
if pct >= MIN_ATTENDANCE:
[Link](student)
else:
[Link](student)
print(f'{student:<12}{present:>8}{absent:>8}{pct:>6.1f}% {bar}
{status}')
print('-'*68)
print(f'Eligible ({len(eligible)}): {', '.join(eligible)}')
if ineligible:
print(f'Ineligible ({len(ineligible)}): {', '.join(ineligible)}')
print('WARNING: Ineligible students cannot appear for final
exam.')
Corporate Example 3: Product Inventory Report
inventory_report.py
# Used in every e-commerce and retail system
inventory = [
{'sku':'SKU001','name':'Laptop Pro 15',
'category':'Electronics','stock':45, 'price':89999,'min_stock':10},
{'sku':'SKU002','name':'Wireless Mouse',
'category':'Accessories', 'stock':3, 'price':1299, 'min_stock':20},
{'sku':'SKU003','name':'USB-C Hub',
'category':'Accessories', 'stock':0, 'price':2499, 'min_stock':15},
{'sku':'SKU004','name':'Monitor 27"',
'category':'Electronics','stock':18, 'price':32000,'min_stock':5},
{'sku':'SKU005','name':'Mechanical KB',
'category':'Accessories', 'stock':7, 'price':4599, 'min_stock':10},
{'sku':'SKU006','name':'Laptop Stand',
'category':'Accessories', 'stock':55, 'price':999, 'min_stock':25},
]
# Category-wise summary using loops
categories = {}
alerts = []
for item in inventory:
cat = item['category']
if cat not in categories:
categories[cat] = {'items':0,'total_value':0,'out_of_stock':0}
categories[cat]['items'] += 1
categories[cat]['total_value'] += item['stock'] * item['price']
if item['stock'] == 0:
categories[cat]['out_of_stock'] += 1
[Link](f'OUT OF STOCK: {item["name"]} ({item["sku"]})')
elif item['stock'] < item['min_stock']:
[Link](f'LOW STOCK : {item["name"]} — {item["stock"]}
units (min: {item["min_stock"]})')
print('=== INVENTORY SUMMARY BY CATEGORY ===')
for cat, data in [Link]():
print(f'{cat:<15} | Items:{data["items"]:>3} | Value: Rs
{data["total_value"]:>10,} | OOS:{data["out_of_stock"]:>2}')
if alerts:
print('\n=== STOCK ALERTS ===')
for alert in alerts:
print(f' ⚠ {alert}')
PART 14 — DEBUGGING PROBLEMS
10 Debugging Problems: Find and Fix the Bugs
Each program below has one or more bugs. Find the bug, explain why it is wrong, and write the
corrected version.
Debug 1 — Off-by-One
Find the bug
# Goal: print numbers 1 to 10 inclusive
for i in range(10):
print(i)
Bug: range(10) gives 0-9. Fix: range(1, 11)
Debug 2 — Accumulator Reset
Find the bug
scores = [85, 92, 78, 91, 74]
for score in scores:
total = 0
total += score
print(f'Total: {total}')
Bug: total = 0 is inside the loop — resets every iteration. Final total = last score only. Fix: move total = 0
above the loop.
Debug 3 — Indentation Trap
Find the bug
count = 0
while count < 5:
print(count)
count += 1 # This is outside the loop!
Bug: count += 1 is not indented — it's outside the while block. The loop runs forever. Fix: indent count
+= 1 by 4 spaces.
Debug 4 — Wrong range()
Find the bug
names = ['Suraj', 'Priya', 'Rahul']
for i in range(len(names) + 1):
print(names[i])
Bug: range(len(names)+1) goes to index 3, but valid indices are 0-2. IndexError on last iteration. Fix:
range(len(names)) — or better, for name in names.
Debug 5 — Prime Number Logic
Find the bug
# Goal: print only prime numbers between 2 and 20
for num in range(2, 21):
for div in range(2, num):
if num % div == 0:
break
print(num, 'is prime') # Wrong position
Bug: print is inside the inner loop — prints 'is prime' for every non-divisor, not just when the number is
confirmed prime. Fix: use for-else or a is_prime flag — print after the inner loop confirms primality.
Debug 6 — Mutation During Iteration
Find the bug
data = [10, 20, 30, 40, 50]
for item in data:
if item > 25:
[Link](item)
print(data)
Bug: modifying data while iterating causes items to be skipped. Fix: iterate over a copy (data[:]) or use
a list comprehension: data = [x for x in data if x <= 25]
Debug 7 — Missing Method Call
Find the bug
words = ['hello', 'world', 'python']
result = []
for word in words:
[Link]([Link]) # Missing parentheses
print(result)
Bug: [Link] is a method REFERENCE, not a method CALL. result contains function objects, not
strings. Fix: [Link]()
Debug 8 — Nested Loop Output
Find the bug
# Goal: print each row of the matrix on a new line
matrix = [[1,2,3],[4,5,6],[7,8,9]]
for row in matrix:
for val in row:
print(val)
print() # New line is in wrong place
Bug: print(val) without end='' prints each number on its own line. The blank print() at the end just adds
one blank line at the very end. Fix: print(val, end=' ') inside inner loop, and print() after inner loop (inside
outer loop).
Debug 9 — continue vs break confusion
Find the bug
# Goal: find 'Karan' and stop searching
names = ['Raj', 'Priya', 'Karan', 'Arun']
for name in names:
if name == 'Karan':
print('Found Karan!')
continue # This always continues — loop never stops early
Bug: continue is used instead of break. continue just skips the rest of the current iteration but the loop
continues. Fix: replace continue with break.
Debug 10 — pass instead of break
Find the bug
# Goal: stop accumulating once total exceeds 10
total = 0
for i in range(1, 6):
total += i
if total > 10:
pass # Intended to stop — but pass does nothing
print(total) # Prints 15, not the intended early-stop value
Bug: pass does absolutely nothing. The programmer wanted break to stop the loop when total > 10.
Fix: replace pass with break.
PART 15 — MINI PROJECTS
5 Mini Projects: Build Real Loop-Powered Programs
Mini Project 1: Times Table Trainer with Quiz Mode
Full Requirements
PHASE 1 — Display Mode:
Ask user which table (1-12)
Display full multiplication table (1x to 12x) formatted neatly
PHASE 2 — Quiz Mode:
Ask 10 random questions from that table
Accept answer, check it, give immediate feedback
Track score across all 10 questions
PHASE 3 — Result:
Display final score and performance rating
10/10: Perfect! 8-9: Excellent! 6-7: Good. Below 6: Needs Practice.
BONUS: Keep looping until user scores 8+ ('mastery loop')
BONUS: Track which specific multiplications they got wrong and retry those
Mini Project 2: Smart ATM Simulator
Full Requirements
STATE: Starting balance Rs 25,000. Transaction history list (max 10 entries).
MENU (looping until Exit):
1. Check Balance
2. Deposit (validate: positive amount, max Rs 1,00,000 per transaction)
3. Withdraw (validate: positive, multiple of 100, not exceeding balance)
4. Mini Statement (last 5 transactions)
5. Exit
VALIDATION: Use while True loops inside each operation for input validation.
SECURITY: 4-digit PIN required at start. 3 wrong attempts = account locked.
BONUS: Daily withdrawal limit of Rs 25,000 tracked across sessions.
BONUS: Transaction timestamp (use loop counter as pseudo-timestamp).
Mini Project 3: Student Batch Analyser
Full Requirements
INPUT (using loops):
Ask how many students in the batch (N)
For each student: collect name and marks in 5 subjects using a loop
PROCESSING (using loops):
Calculate average, grade, pass/fail for each student
Find class topper, lowest scorer, class average
Grade distribution count (A+, A, B, C, F)
OUTPUT:
Formatted report table (using loops for rows)
Class statistics summary
Visual bar chart of grade distribution (using # characters in a loop)
BONUS: Implement bubble sort using nested loops to rank students by average.
BONUS: Identify students who improved (marks in subject 5 > subject 1).
Mini Project 4: Star Pattern Generator
Full Requirements
Ask user for pattern type:
1. Right Triangle 2. Inverted Triangle 3. Pyramid
4. Diamond 5. Number Triangle 6. Floyd's Triangle
7. Hollow Square 8. Custom Pattern
Ask for size (rows) and character (default: *)
Generate the pattern using nested loops
HOLLOW versions: only print character on border, space inside
ALL in a while loop: keep showing patterns until user selects Exit
BONUS: Mirror each pattern (left and right version)
BONUS: Allow user to input a custom character ('X', '#', '@', etc.)
Mini Project 5: Adya Technology Attendance System
Full Requirements
SETUP (using loops):
Enter batch name and list of students (loop until done)
Enter number of working days (e.g., 30)
ATTENDANCE INPUT (nested loops):
For each day, for each student: mark P (Present) or A (Absent)
Use continue to skip invalid entries (only P or A accepted)
Track late arrivals separately: L (Late) counts as 0.5 present
REPORT GENERATION (loops):
For each student: total present, absent, late, attendance %
Status: Eligible (>=75%), Warning (65-74%), Ineligible (<65%)
Visual attendance bar using # and . characters
ALERTS (loop):
Loop through students and print warnings for those in danger zone
Send detailed report: topper (most present), most absent student
BONUS: Calculate which day had best overall attendance.
BONUS: Project each student's final attendance if they attend all remaining days.
PART 16 — CORPORATE CASE STUDY
Corporate Case Study: How Swiggy Builds Your
Restaurant Feed
Every time you open Swiggy and see restaurant results, thousands of loops have executed in
milliseconds. Let's trace the simplified loop logic behind the feed you see.
swiggy_feed_engine.py — simplified concept
# Simplified version of real feed-building logic
# The actual system processes millions of records per second
def build_restaurant_feed(user):
all_restaurants = database.fetch_by_city([Link])
feed = []
skipped = 0
for restaurant in all_restaurants: # LOOP 1: all restaurants
# FILTER: skip closed restaurants
if not restaurant.is_open:
skipped += 1
continue
# FILTER: skip out of delivery range
distance = haversine([Link], [Link])
if distance > restaurant.max_delivery_km:
skipped += 1
continue
# SCORE: relevance calculation
score = 0
# Cuisine preference boost
for cuisine in [Link]: # LOOP 2: cuisines
if cuisine in user.liked_cuisines:
score += 20
if cuisine in user.disliked_cuisines:
score -= 10
# Rating boost
score += [Link] * 10
# Delivery time score
if restaurant.estimated_delivery_mins <= 20:
score += 20
elif restaurant.estimated_delivery_mins <= 40:
score += 10
else:
score -= 5
# Loyalty bonus
if [Link] in user.order_history: # LOOP 3 (set
lookup: O(1))
score += 25
# Discount available
for offer in restaurant.active_offers: # LOOP 4: current
offers
if offer.is_valid_for(user):
score += 15
break # One valid offer is enough
restaurant.relevance_score = score
[Link](restaurant)
# Sort by relevance score, highest first
[Link](key=lambda r: r.relevance_score, reverse=True)
print(f'Processed {len(all_restaurants)} restaurants.')
print(f'Showing top 20 of {len(feed)} eligible (skipped
{skipped})')
return feed[:20] # Top 20 shown to user
# Notice how concepts from Chapters 2 AND 3 combine here:
# for loops, while, if-elif-else, break, continue, and sorting.
# This is what real production code looks like.
Every restaurant you see on Swiggy is the output of loops exactly like these. The for loop over
restaurants, the nested loop over cuisines, the break on the first valid offer — these are not teaching
examples. This is production thinking.
And you now understand all of it.
PART 17 — CHAPTER SUMMARY
Chapter Summary: What You Learned
Chapter 3 Complete — Full Master Checklist
while LOOP: Runs while condition is True. Must update condition each iteration.
while True: is intentional — always pair with break.
while-else: else runs only when condition becomes False naturally.
for LOOP: Iterates over any iterable (list, str, dict, tuple, range, file...).
for-else: else runs only if no break was triggered.
Preferred over while when iterating a known collection.
range(): range(stop), range(start,stop), range(start,stop,step).
Memory-efficient — does NOT store all values. Use over list(range(...)).
break: Exits the ENTIRE loop immediately. Only exits innermost in nested loops.
continue: Skips REST of current iteration. Loop continues with next item.
pass: Does nothing. Placeholder for future code or empty block requirement.
enumerate(lst, start=1): Gives (index, value) pairs. Use instead of range(len()).
zip(a, b, c): Pairs items from multiple iterables. Stops at shortest.
NESTED LOOPS: Inner runs fully for every outer iteration. O(n^2) complexity.
Avoid going deeper than 2-3 levels. Use functions to flatten.
ACCUMULATOR PATTERN: Initialize BEFORE loop. Update INSIDE. Read AFTER.
LIST COMPREHENSION: [expr for x in iterable if condition]. Fast, readable, Pythonic.
GENERATOR EXPRESSION: (expr for x in iterable) — memory-efficient for large data.
BUILT-INS OVER LOOPS: sum, max, min, sorted, any, all, filter, map — use them.
SENIOR RULES: Flat over deep. Extract loop bodies to functions. O(n) over O(n^2).
PART 18 — QUICK REVISION NOTES
Quick Revision Notes: Read Before Your Interview
CONCEPT ONE-LINE ANSWER
while loop Runs while condition is True. Must have something that
makes condition False.
for loop Iterates over every item in a collection or range. Preferred
over while.
range(1,10,2) Produces: 1, 3, 5, 7, 9 (start, stop-exclusive, step).
break Exits the entire loop immediately. Only innermost loop in
nested.
continue Skips rest of current iteration. Loop continues with next item.
pass Does absolutely nothing. Syntactic placeholder for empty
blocks.
for-else / while-else else runs ONLY if loop completed without break being hit.
enumerate(lst, start=1) Gives (1,item1), (2,item2)... instead of (0,item1)...
zip(a, b) Pairs items: (a[0],b[0]), (a[1],b[1])... Stops at shortest.
List comprehension [x*2 for x in nums if x>0] — one-line filtered transformation.
Generator expression (x*2 for x in nums) — like list comp but computes lazily, no
memory.
Accumulator pattern total=0 before loop. total+=x inside. Read total after.
Infinite loop while True: is intentional. Forgetting i+=1 is a bug. Ctrl+C
kills.
Nested loop complexity 2 nested loops = O(n^2). 3 nested = O(n^3). Avoid > 2 levels.
Mutating during iteration Never remove from list while looping. Use a copy or
comprehension.
O(n^2) vs O(n) search Use set/dict membership (O(1)) instead of nested loops
(O(n^2)).
range(len()) rule Only use when modifying by index. Otherwise iterate directly.
sum/max/min/any/all Built-ins that replace common 5-line accumulator loops.
PART 19 — PRACTICE QUESTIONS
Practice Questions: 60 Questions to Master Chapter 3
Beginner Questions (30)
11. What is a loop? Why do computers need repetition?
12. Write a while loop that prints numbers 1 to 10.
13. What is the difference between a for loop and a while loop?
14. Write a for loop that prints every character in the word 'PYTHON'.
15. What does range(5) produce? What about range(2, 8)?
16. Write a program to calculate sum of numbers from 1 to 100 using a loop.
17. What is an infinite loop? Write one example and how to kill it.
18. What does break do? Write a code example.
19. What does continue do? How is it different from break?
20. Write a loop to print only odd numbers from 1 to 20.
21. What does range(10, 0, -1) produce? Write a use case.
22. Write nested loops to print the 7 times table (7x1 to 7x12).
23. What is the purpose of pass? When would you use it?
24. Write a while loop that keeps asking for a positive number until user provides one.
25. What is enumerate()? Show how it replaces range(len(list)).
26. Write a program to count how many times the letter 'p' appears in 'programming'.
27. What is a nested loop? Give a real-world analogy.
28. Write nested loops to print a 4x4 grid of asterisks.
29. What happens when you forget count += 1 in a while loop?
30. Write a loop to find the largest number in a list without using max().
31. What does zip() do? Show it combining two lists.
32. Write a loop to reverse the string 'algorithm' character by character.
33. What is the for-else clause? Write an example that uses it correctly.
34. Write a program to print the first 15 Fibonacci numbers using a while loop.
35. Write a loop to count vowels and consonants separately in a user-input string.
36. What is a list comprehension? Convert this for loop: for x in nums: [Link](x**2)
37. Write a loop to check if a number entered by the user is prime.
38. What is the difference between while True: and while some_condition:?
39. Write a program that prints the right-angled star triangle pattern (5 rows).
40. Write a loop to calculate N! (factorial of N).
Intermediate Questions (20)
41. Explain the accumulator pattern with three different real-world examples.
42. Write a loop to flatten [[1,2],[3,4],[5,6]] into [1,2,3,4,5,6].
43. What is the difference between a list comprehension and a generator expression?
44. Write a program to find all prime numbers between 2 and 100.
45. Explain with code why you must never modify a list while iterating over it.
46. Write a loop to build a dictionary from two parallel lists using zip().
47. What is the while True + break pattern? Write a real-world example.
48. Write a loop to transpose a 3x3 matrix (list of lists).
49. Explain why break in a nested loop only exits the innermost loop.
50. Write a loop to group a flat list of students into a dict by grade.
51. What are any() and all()? Replace manual loops with them.
52. Write a loop to count word frequency in a paragraph string.
53. What is the walrus operator := and how does it simplify while loops?
54. Write a loop to remove duplicates from a list while preserving order.
55. Explain the time complexity difference between O(n) and O(n^2) loops.
56. Write a batch email validator that processes a list and separates valid/invalid.
57. Write a loop that simulates a round-robin tournament schedule.
58. What is [Link]()? Show it flattening a nested list.
59. Write a payroll processor loop for 5 employees with PF and tax deductions.
60. Write a loop to detect the first duplicate value in a list in O(n) time.
Advanced Questions (10)
61. What is a generator function (using yield)? How does it differ from a list comprehension?
62. Implement a custom range() function using a generator with yield.
63. Explain Python's iterator protocol — what are __iter__ and __next__?
64. How does Python's for loop actually work internally? What does it call on the collection?
65. What is tail recursion? Why doesn't Python optimize it, and what's the loop alternative?
66. Implement map() and filter() from scratch using loops, then compare to built-ins.
67. Explain how [Link]() and [Link]() optimize loops over huge data.
68. Write a coroutine using yield that processes a stream of numbers lazily.
69. What is the time complexity of a nested list comprehension like [[f(x,y) for x in row] for row in
matrix]?
70. Explain the difference between eager and lazy evaluation in the context of Python loops.
"Loops are the heartbeat of software. Every recommendation you've ever
received, every transaction processed, every report generated — a loop
produced it. Now you write those loops. Chapter 4 awaits."
— Your Python Mentor
END OF CHAPTER 3