Python Loops: for, while, nested

Python Loops Interview Questions

What are loops in Python and why are they used?
Loops are used to repeatedly execute a block of code. They automate repetitive tasks, process collections of data, and implement iterative algorithms. Python has two main loop types: for loops and while loops.
What is the basic syntax of a for loop in Python?
# Basic syntax for item in iterable: # code to execute for each item # Examples for i in range(5): # 0, 1, 2, 3, 4 print(i) for char in "Hello": # H, e, l, l, o print(char) for num in [1, 2, 3, 4, 5]: # 1, 2, 3, 4, 5 print(num * 2)
The for loop iterates over each item in an iterable (list, string, tuple, dictionary, set, or range).
What is the basic syntax of a while loop in Python?
# Basic syntax while condition: # code to execute while condition is True # Example: Count from 1 to 5 count = 1 while count <= 5: print(count) count += 1 # Important: Update the condition variable # Example: User input until valid password = "" while password != "secret": password = input("Enter password: ")
The while loop continues executing as long as the condition remains True.
What is the difference between for loop and while loop?
Aspectfor loopwhile loop
When to useWhen you know number of iterationsWhen iterations depend on condition
InitializationAutomatic (gets next item)Manual (before loop)
ConditionImplied (items in iterable)Explicit (boolean expression)
IncrementAutomatic (next iteration)Manual (inside loop)
RiskNo infinite loop (finite iterable)Risk of infinite loop
What are nested loops in Python?
# Nested for loops for i in range(3): # Outer loop for j in range(2): # Inner loop print(f"({i}, {j})") # Output: (0,0), (0,1), (1,0), (1,1), (2,0), (2,1) # Nested while loops i = 1 while i <= 3: j = 1 while j <= 2: print(f"i={i}, j={j}") j += 1 i += 1 # Mixed nesting for row in range(3): col = 0 while col < 2: print(f"[{row},{col}]") col += 1
A loop inside another loop. The inner loop completes all iterations for each iteration of the outer loop.
What is the range() function and how is it used with for loops?
# range(stop) - 0 to stop-1 for i in range(5): # 0, 1, 2, 3, 4 print(i) # range(start, stop) - start to stop-1 for i in range(2, 6): # 2, 3, 4, 5 print(i) # range(start, stop, step) - with step for i in range(1, 10, 2): # 1, 3, 5, 7, 9 print(i) # Negative step for i in range(5, 0, -1): # 5, 4, 3, 2, 1 print(i) # Common patterns for i in range(len(my_list)): # Index-based iteration print(f"Index {i}: {my_list[i]}") for i in range(10, 0, -1): # Countdown print(i) print("Blast off!")
What are loop control statements (break, continue, pass)?
# break - exit the loop entirely for i in range(10): if i == 5: break # Loop stops at i=5 print(i) # Output: 0, 1, 2, 3, 4 # continue - skip current iteration, continue with next for i in range(5): if i == 2: continue # Skip i=2 print(i) # Output: 0, 1, 3, 4 # pass - do nothing (placeholder) for i in range(5): if i == 3: pass # Nothing happens print(i) # Output: 0, 1, 2, 3, 4 # else with loops - executes when loop completes normally (no break) for i in range(5): print(i) else: print("Loop completed successfully")
What is an infinite loop and how to create/avoid it?
# Infinite while loop (condition always True) # while True: # print("This runs forever!") # Common infinite loop patterns # count = 1 # while count < 5: # Forgot to increment count # print(count) # Infinite loop! # How to avoid infinite loops count = 1 while count < 5: print(count) count += 1 # Always update condition variable # Using break to exit infinite loop while True: user_input = input("Enter 'quit' to exit: ") if user_input == 'quit': break print(f"You entered: {user_input}") # Safe pattern with timeout import time start_time = time.time() max_time = 10 # seconds while True: # Process something if time.time() - start_time > max_time: print("Timeout!") break
How to iterate over dictionaries with for loops?
my_dict = {'name': 'Alice', 'age': 30, 'city': 'New York'} # Iterate over keys (default) for key in my_dict: print(f"Key: {key}") # Explicitly iterate over keys for key in my_dict.keys(): print(f"Key: {key}") # Iterate over values for value in my_dict.values(): print(f"Value: {value}") # Iterate over key-value pairs for key, value in my_dict.items(): print(f"{key}: {value}") # Practical example student_grades = {'John': 85, 'Emma': 92, 'Mike': 78} for name, grade in student_grades.items(): if grade >= 90: print(f"{name}: A") elif grade >= 80: print(f"{name}: B")
What is enumerate() and how is it used with for loops?
# enumerate() adds counter to iterable fruits = ['apple', 'banana', 'cherry'] # Without enumerate index = 0 for fruit in fruits: print(f"{index}: {fruit}") index += 1 # With enumerate (much cleaner!) for index, fruit in enumerate(fruits): print(f"{index}: {fruit}") # With custom start index for index, fruit in enumerate(fruits, start=1): print(f"{index}. {fruit}") # Practical example students = ['Alice', 'Bob', 'Charlie'] for position, student in enumerate(students, start=1): print(f"Position {position}: {student}") # Enumerate with condition for i, num in enumerate([10, 20, 30, 40, 50]): if num > 25: print(f"Index {i}: {num} is greater than 25")
What is zip() and how is it used with for loops?
# zip() combines multiple iterables names = ['Alice', 'Bob', 'Charlie'] ages = [25, 30, 35] cities = ['NYC', 'LA', 'Chicago'] # Iterate over multiple lists simultaneously for name, age, city in zip(names, ages, cities): print(f"{name} is {age} years old and lives in {city}") # With enumerate and zip for i, (name, age) in enumerate(zip(names, ages), start=1): print(f"{i}. {name}: {age} years") # Different length lists - stops at shortest list1 = [1, 2, 3] list2 = ['a', 'b'] for num, letter in zip(list1, list2): print(f"{num}{letter}") # Output: 1a, 2b (3 is skipped) # To handle different lengths, use itertools.zip_longest import itertools for num, letter in itertools.zip_longest(list1, list2, fillvalue='-'): print(f"{num}{letter}") # Output: 1a, 2b, 3-
How to use else clause with loops?
# else executes when loop completes normally (no break) # For loop with else for i in range(5): print(i) else: print("Loop completed without break") # With break - else won't execute for i in range(5): if i == 3: break print(i) else: print("This won't print because of break") # While loop with else count = 0 while count < 3: print(count) count += 1 else: print("While loop completed") # Practical example: Search with else numbers = [1, 3, 5, 7, 9] search_for = 6 for num in numbers: if num == search_for: print(f"Found {search_for}") break else: print(f"{search_for} not found in list") # This executes
What are list comprehensions and how do they relate to loops?
# List comprehension - concise way to create lists # Traditional for loop squares = [] for i in range(5): squares.append(i**2) print(squares) # [0, 1, 4, 9, 16] # List comprehension equivalent squares = [i**2 for i in range(5)] print(squares) # [0, 1, 4, 9, 16] # With condition (if) even_squares = [i**2 for i in range(10) if i % 2 == 0] print(even_squares) # [0, 4, 16, 36, 64] # Nested loops in comprehension pairs = [(x, y) for x in range(3) for y in range(2)] print(pairs) # [(0,0), (0,1), (1,0), (1,1), (2,0), (2,1)] # Dictionary comprehension square_dict = {x: x**2 for x in range(5)} print(square_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} # Set comprehension unique_squares = {x**2 for x in range(-5, 6)} print(unique_squares) # {0, 1, 4, 9, 16, 25}
How to iterate over multiple sequences simultaneously?
# Method 1: Using zip() (most common) names = ['Alice', 'Bob', 'Charlie'] ages = [25, 30, 35] for name, age in zip(names, ages): print(f"{name} is {age} years old") # Method 2: Using range() with index for i in range(len(names)): print(f"{names[i]} is {ages[i]} years old") # Method 3: Using enumerate() with zip for i, (name, age) in enumerate(zip(names, ages)): print(f"{i+1}. {name}: {age}") # Method 4: Using itertools.zip_longest for different lengths import itertools list1 = [1, 2, 3] list2 = ['a', 'b'] for a, b in itertools.zip_longest(list1, list2, fillvalue='N/A'): print(f"{a} - {b}") # 1-a, 2-b, 3-N/A # Method 5: Manual index with while loop i = 0 while i < len(names) and i < len(ages): print(f"{names[i]}: {ages[i]}") i += 1
What are common loop patterns and idioms?
# 1. Accumulator pattern total = 0 for num in [1, 2, 3, 4, 5]: total += num print(f"Total: {total}") # 2. Counter pattern count = 0 for char in "hello world": if char == 'l': count += 1 print(f"Count of 'l': {count}") # 3. Search pattern found = False for item in [1, 3, 5, 7, 9]: if item == 5: found = True break print(f"Found 5: {found}") # 4. Filter pattern evens = [] for num in range(10): if num % 2 == 0: evens.append(num) print(f"Even numbers: {evens}") # 5. Transform pattern squared = [] for num in range(5): squared.append(num ** 2) print(f"Squares: {squared}") # 6. Nested loop for matrix matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] for row in matrix: for element in row: print(element, end=' ') print() # New line after each row
How to avoid modifying a list while iterating over it?
# Problem: Modifying list while iterating numbers = [1, 2, 3, 4, 5] # for num in numbers: # if num % 2 == 0: # numbers.remove(num) # This causes issues! # Solution 1: Create a copy numbers = [1, 2, 3, 4, 5] for num in numbers.copy(): # or numbers[:] if num % 2 == 0: numbers.remove(num) print(numbers) # [1, 3, 5] # Solution 2: Use list comprehension (create new list) numbers = [1, 2, 3, 4, 5] numbers = [num for num in numbers if num % 2 != 0] print(numbers) # [1, 3, 5] # Solution 3: Iterate over indices in reverse numbers = [1, 2, 3, 4, 5] for i in range(len(numbers)-1, -1, -1): if numbers[i] % 2 == 0: numbers.pop(i) print(numbers) # [1, 3, 5] # Solution 4: Collect items to remove, then remove them numbers = [1, 2, 3, 4, 5] to_remove = [] for num in numbers: if num % 2 == 0: to_remove.append(num) for item in to_remove: numbers.remove(item) print(numbers) # [1, 3, 5]
What is the difference between iterating over a list vs iterating over its indices?
fruits = ['apple', 'banana', 'cherry'] # Method 1: Iterate over elements (Pythonic) for fruit in fruits: print(fruit) # Output: apple, banana, cherry # Method 2: Iterate over indices for i in range(len(fruits)): print(f"{i}: {fruits[i]}") # Output: 0: apple, 1: banana, 2: cherry # When to use indices: # 1. Need index for something else for i in range(len(fruits)): print(f"Index {i}: {fruits[i]}") # 2. Modifying elements for i in range(len(fruits)): fruits[i] = fruits[i].upper() print(fruits) # ['APPLE', 'BANANA', 'CHERRY'] # 3. Accessing multiple lists at same index names = ['Alice', 'Bob', 'Charlie'] ages = [25, 30, 35] for i in range(len(names)): print(f"{names[i]} is {ages[i]} years old") # Better: Use enumerate() for i, fruit in enumerate(fruits): print(f"{i}: {fruit}")
How to use loops with files?
# Reading a file line by line with open('data.txt', 'r') as file: for line in file: print(line.strip()) # strip() removes newline # With line numbers with open('data.txt', 'r') as file: for line_num, line in enumerate(file, start=1): print(f"{line_num}: {line.strip()}") # Reading specific number of lines with open('data.txt', 'r') as file: for i in range(5): # Read first 5 lines line = file.readline() if not line: # End of file break print(line.strip()) # Processing CSV data import csv with open('data.csv', 'r') as file: csv_reader = csv.reader(file) for row in csv_reader: # Process each row (list of values) print(row) # Writing to file in a loop data = ['Line 1', 'Line 2', 'Line 3'] with open('output.txt', 'w') as file: for line in data: file.write(line + '\n')
What are generator expressions and how do they relate to loops?
# Generator expression - memory efficient alternative to list comprehension # List comprehension (creates full list in memory) squares_list = [x**2 for x in range(1000000)] # Uses lots of memory # Generator expression (creates generator object) squares_gen = (x**2 for x in range(1000000)) # Memory efficient # Using generator in loop for square in (x**2 for x in range(5)): print(square) # With condition even_squares = (x**2 for x in range(10) if x % 2 == 0) for num in even_squares: print(num) # Converting generator to list gen = (x for x in range(5)) my_list = list(gen) # [0, 1, 2, 3, 4] # Generator with sum() - no intermediate list total = sum(x**2 for x in range(1000)) # Memory efficient # Compare memory usage import sys list_comp = [x**2 for x in range(1000)] gen_exp = (x**2 for x in range(1000)) print(f"List size: {sys.getsizeof(list_comp)} bytes") print(f"Generator size: {sys.getsizeof(gen_exp)} bytes")
What are common loop mistakes and how to avoid them?
# 1. Infinite loop (forgot to update condition) # count = 0 # while count < 5: # print(count) # Forgot count += 1 # 2. Modifying list while iterating # items = [1, 2, 3, 4] # for item in items: # items.remove(item) # Unexpected behavior # 3. Using same variable name in nested loops for i in range(3): for i in range(2): # Reusing variable name print(i) # Inner loop overwrites i # 4. Off-by-one errors with range() for i in range(5): # 0 to 4 (not 1 to 5) print(i) # 5. Forgetting to convert range to list r = range(5) print(r) # range(0, 5) - not a list! print(list(r)) # [0, 1, 2, 3, 4] # 6. Using loop variable after loop for i in range(5): pass print(i) # i = 4 (last value) - can be confusing # 7. Not using enumerate when index is needed fruits = ['apple', 'banana'] # Instead of: for i in range(len(fruits)): print(f"{i}: {fruits[i]}") # Use: for i, fruit in enumerate(fruits): print(f"{i}: {fruit}")
Note: These questions cover Python loops comprehensively. Remember: Use for loops when you know the number of iterations, and while loops when iterations depend on a condition. Always be cautious of infinite loops. Python offers many elegant loop constructs like list comprehensions, generator expressions, enumerate(), and zip() that can make your code more readable and efficient.
Python Loops (for, while, nested) Next