Back to blog
Backend Systemsbeginner

Python Control Flow: Conditionals, Loops, and Comprehensions

Master Python control flow with if/elif/else, while and for loops, range(), break/continue/pass, nested loops, list/dict comprehensions, generator expressions, and classic algorithm examples.

Asma HafeezApril 17, 202620 min read
pythoncontrol-flowloopscomprehensionsalgorithmsbeginner
Share:š•

Python Control Flow: Conditionals, Loops, and Comprehensions

Control flow determines the order in which code executes. Instead of running top to bottom, programs can make decisions, repeat operations, and skip code. Python's control flow is clean and expressive — once you master it, you can write algorithms that read almost like English.

This guide covers every control flow construct in Python with real-world examples, including three complete algorithm implementations at the end.


1. if / elif / else

The if statement is the fundamental decision-making tool. It evaluates a condition and executes code only when that condition is True.

Basic if

Python
temperature = 35

if temperature > 30:
    print("It's hot outside!")
    print("Stay hydrated.")

print("Program continues here regardless.")

if / else

Python
score = 72

if score >= 60:
    print("You passed!")
else:
    print("You failed. Please review the material.")

if / elif / else

Use elif (else-if) to check multiple conditions in sequence. Python checks each condition in order and executes only the first matching block.

Python
score = 84

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
elif score >= 60:
    grade = "D"
else:
    grade = "F"

print(f"Your grade is: {grade}")  # Your grade is: B

Why the Order Matters

Python
# WRONG: the first condition is too broad
score = 95
if score >= 60:
    grade = "D"          # This matches 95!
elif score >= 90:
    grade = "A"          # Never reached for 95
# grade is "D" for a score of 95 — bug!

# CORRECT: check from most specific to least specific
if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 60:
    grade = "D"
# grade is "A" for score 95 — correct

Nested if Statements

Python
is_logged_in = True
is_admin = False
account_suspended = False

if is_logged_in:
    if account_suspended:
        print("Your account is suspended.")
    elif is_admin:
        print("Welcome, administrator!")
    else:
        print("Welcome back!")
else:
    print("Please log in.")

One-Line if (Ternary Expression)

Python
# Syntax: value_if_true if condition else value_if_false
age = 20
status = "adult" if age >= 18 else "minor"
print(status)  # adult

# Can be nested — but don't overdo it
score = 75
grade = "A" if score >= 90 else "B" if score >= 80 else "C" if score >= 70 else "F"
print(grade)  # C

2. Comparison Operators (Review)

Python
x = 10

# All comparison operators
print(x == 10)   # True  — equal
print(x != 5)    # True  — not equal
print(x > 5)     # True  — greater than
print(x < 20)    # True  — less than
print(x >= 10)   # True  — greater than or equal
print(x <= 10)   # True  — less than or equal

# Chained comparisons
print(1 < x < 100)     # True
print(10 <= x <= 10)   # True

# String comparison (lexicographic)
print("apple" < "banana")   # True
print("Z" < "a")            # True (uppercase before lowercase in ASCII)
print("cat" == "cat")       # True

3. Truthy and Falsy Values

Python's if statement does not require a strict boolean — it evaluates any expression's truthiness.

What Is Falsy?

Python
# ALL of these are falsy — if condition will be False
falsy_values = [
    False,
    0,          # integer zero
    0.0,        # float zero
    0j,         # complex zero
    "",         # empty string
    [],         # empty list
    (),         # empty tuple
    {},         # empty dict
    set(),      # empty set
    None,       # None
]

for val in falsy_values:
    if not val:
        print(f"{repr(val):15} is falsy")

What Is Truthy?

Python
# These are all truthy
print(bool(1))          # True — any non-zero number
print(bool(-1))         # True
print(bool("hello"))    # True — any non-empty string
print(bool(" "))        # True — whitespace is truthy!
print(bool([0]))        # True — list with one item (even if item is falsy)
print(bool({"key": 0})) # True — non-empty dict

Pythonic Use of Truthiness

Python
# Instead of: if len(my_list) > 0:
my_list = [1, 2, 3]
if my_list:
    print("List has items")

# Instead of: if name != "":
name = "Alice"
if name:
    print(f"Hello, {name}")

# Instead of: if result is not None:
result = some_function_that_might_return_none = lambda: 42
result = result()
if result is not None:   # Explicit — use when None has meaning distinct from 0
    print(result)

# Guard clause pattern — fail fast
def process_order(order):
    if not order:
        return "No order provided"
    if not order.get("items"):
        return "Order has no items"
    if order.get("total", 0) <= 0:
        return "Invalid total"
    
    # Main logic here — we know order is valid
    return f"Processing {len(order['items'])} items"

4. while Loops

A while loop executes a block of code repeatedly as long as its condition is True.

Basic while Loop

Python
# Count down
count = 5
while count > 0:
    print(count)
    count -= 1
print("Blast off!")
# 5 4 3 2 1
# Blast off!

Infinite Loop with break

Python
# Input validation loop — common real-world pattern
while True:
    answer = input("Enter 'yes' or 'no': ").strip().lower()
    if answer in ("yes", "no"):
        break
    print("Invalid input. Please try again.")

print(f"You entered: {answer}")

while/else

Python's while/else is unusual — the else block runs when the condition becomes False normally (not via break).

Python
# Search for a user
users = ["alice", "bob", "charlie"]
target = "dave"
index = 0

while index < len(users):
    if users[index] == target:
        print(f"Found {target} at index {index}")
        break
    index += 1
else:
    print(f"{target} not found in users list")
# Output: dave not found in users list

Common while Loop Patterns

Python
# Reading until a sentinel value
print("Enter numbers (0 to stop):")
total = 0
count = 0
while True:
    num = float(input("Number: "))
    if num == 0:
        break
    total += num
    count += 1

if count > 0:
    print(f"Average: {total / count:.2f}")

# Retry with max attempts
import random

MAX_ATTEMPTS = 3
attempts = 0

while attempts < MAX_ATTEMPTS:
    # Simulate a flaky operation
    success = random.random() > 0.5
    attempts += 1
    
    if success:
        print(f"Success on attempt {attempts}")
        break
    print(f"Attempt {attempts} failed, retrying...")
else:
    print(f"Failed after {MAX_ATTEMPTS} attempts")

5. for Loops

A for loop iterates over any iterable object — lists, strings, ranges, tuples, dicts, files, etc.

Iterating Over Common Types

Python
# List
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

# String — iterates over characters
for char in "Python":
    print(char, end=" ")  # P y t h o n

# Tuple
coordinates = (10, 20)
for coord in coordinates:
    print(coord)

# Dict — iterates over KEYS by default
scores = {"Alice": 95, "Bob": 87, "Charlie": 92}
for name in scores:
    print(f"{name}: {scores[name]}")

# Dict items — key-value pairs
for name, score in scores.items():
    print(f"{name}: {score}")

# Dict keys and values explicitly
for key in scores.keys():
    print(key)
for value in scores.values():
    print(value)

enumerate() — Index and Value Together

Python
fruits = ["apple", "banana", "cherry"]

# Without enumerate — ugly
for i in range(len(fruits)):
    print(f"{i}: {fruits[i]}")

# With enumerate — Pythonic
for i, fruit in enumerate(fruits):
    print(f"{i}: {fruit}")

# Start from 1
for i, fruit in enumerate(fruits, start=1):
    print(f"{i}. {fruit}")
# 1. apple
# 2. banana
# 3. cherry

zip() — Iterate Two Lists in Parallel

Python
names = ["Alice", "Bob", "Charlie"]
scores = [95, 87, 92]

for name, score in zip(names, scores):
    print(f"{name}: {score}")

# zip stops at the shortest iterable
a = [1, 2, 3, 4, 5]
b = ["a", "b", "c"]
for x, y in zip(a, b):
    print(x, y)
# 1 a
# 2 b
# 3 c
# (4 and 5 are ignored)

# Unzip — transpose a list of pairs
pairs = [(1, "a"), (2, "b"), (3, "c")]
numbers, letters = zip(*pairs)
print(list(numbers))  # [1, 2, 3]
print(list(letters))  # ['a', 'b', 'c']

for/else

Like while/else, the else block runs if the loop completes without a break.

Python
# Find a prime factor
def smallest_factor(n):
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            print(f"{n} is divisible by {i}")
            break
    else:
        print(f"{n} is prime")

smallest_factor(17)   # 17 is prime
smallest_factor(15)   # 15 is divisible by 3

6. range()

range() generates a sequence of integers. It is lazy — it does not create a list in memory.

Python
# range(stop)
for i in range(5):
    print(i)  # 0 1 2 3 4

# range(start, stop)
for i in range(2, 7):
    print(i)  # 2 3 4 5 6

# range(start, stop, step)
for i in range(0, 20, 4):
    print(i)  # 0 4 8 12 16

# Counting backwards
for i in range(10, 0, -1):
    print(i, end=" ")  # 10 9 8 7 6 5 4 3 2 1

# Converting to list
print(list(range(5)))         # [0, 1, 2, 3, 4]
print(list(range(1, 10, 2)))  # [1, 3, 5, 7, 9]

# Range is memory-efficient
import sys
r = range(1_000_000)
lst = list(range(1_000_000))
print(sys.getsizeof(r))    # 48 bytes
print(sys.getsizeof(lst))  # ~8,448,728 bytes

# range supports len(), in, indexing
r = range(10)
print(len(r))       # 10
print(5 in r)       # True
print(r[3])         # 3
print(r[-1])        # 9
print(r[2:7])       # range(2, 7)

7. break, continue, and pass

break — Exit the Loop Immediately

Python
# Find first even number
numbers = [3, 7, 2, 9, 4, 6]
for n in numbers:
    if n % 2 == 0:
        print(f"First even number: {n}")
        break
# First even number: 2

# break in nested loops only exits the innermost loop
for i in range(3):
    for j in range(3):
        if j == 1:
            break        # only breaks inner loop
        print(f"({i},{j})", end=" ")
# (0,0) (1,0) (2,0)

continue — Skip to Next Iteration

Python
# Skip even numbers
for n in range(10):
    if n % 2 == 0:
        continue    # skip even numbers
    print(n, end=" ")
# 1 3 5 7 9

# Process only valid data
data = [1, None, 3, None, 5, 6]
total = 0
for item in data:
    if item is None:
        continue    # skip None values
    total += item

print(f"Sum: {total}")  # Sum: 15

pass — Do Nothing (Placeholder)

pass is a no-op statement. It is used when syntax requires a block but you have nothing to write yet.

Python
# Placeholder for future code
def process_payment():
    pass  # TODO: implement payment processing

class DatabaseConnection:
    pass  # TODO: implement class

# In a try/except — silently ignore an error
try:
    risky_operation = int("not a number")
except ValueError:
    pass  # intentionally ignore

# In a loop — skip with no side effects
for i in range(10):
    if i % 2 == 0:
        pass    # could add handling later
    else:
        print(i, end=" ")
# 1 3 5 7 9

8. Nested Loops

Nested loops are loops inside loops. They are essential for working with 2D data like grids and matrices.

Python
# Multiplication table
print("Multiplication Table (1-5):")
print("    ", end="")
for j in range(1, 6):
    print(f"{j:4}", end="")
print()

for i in range(1, 6):
    print(f"{i:4}", end="")
    for j in range(1, 6):
        print(f"{i*j:4}", end="")
    print()

# Output:
#        1   2   3   4   5
#     1   1   2   3   4   5
#     2   2   4   6   8  10
#     3   3   6   9  12  15
#     4   4   8  12  16  20
#     5   5  10  15  20  25
Python
# 2D grid traversal
grid = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# Sum all elements
total = 0
for row in grid:
    for cell in row:
        total += cell
print(f"Total: {total}")  # 45

# Find a value
target = 6
found = False
for i, row in enumerate(grid):
    for j, cell in enumerate(row):
        if cell == target:
            print(f"Found {target} at row {i}, col {j}")
            found = True
            break
    if found:
        break

9. List Comprehensions

List comprehensions are a concise, Pythonic way to create lists. They are often faster than equivalent for loops because they are optimized in CPython.

Basic Syntax

Python
# Syntax: [expression for item in iterable if condition]

# Traditional loop
squares = []
for n in range(10):
    squares.append(n ** 2)

# List comprehension
squares = [n ** 2 for n in range(10)]
print(squares)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

With Filtering

Python
# Only even squares
even_squares = [n ** 2 for n in range(10) if n % 2 == 0]
print(even_squares)
# [0, 4, 16, 36, 64]

# Strings: filter and transform
words = ["hello", "world", "python", "is", "great"]
long_words_upper = [w.upper() for w in words if len(w) > 4]
print(long_words_upper)
# ['HELLO', 'WORLD', 'PYTHON', 'GREAT']

Nested List Comprehensions

Python
# Flatten a 2D list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [cell for row in matrix for cell in row]
print(flat)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Cartesian product
colors = ["red", "blue"]
sizes = ["S", "M", "L"]
variants = [(color, size) for color in colors for size in sizes]
print(variants)
# [('red', 'S'), ('red', 'M'), ('red', 'L'), ('blue', 'S'), ('blue', 'M'), ('blue', 'L')]

# Matrix transpose
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [[row[i] for row in matrix] for i in range(3)]
print(transposed)
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

When NOT to Use List Comprehensions

Python
# If the logic is complex, use a regular loop for readability
# Hard to read:
result = [do_complex_transform(x) for x in data if predicate(x) and another_predicate(x)]

# Better as a loop:
result = []
for x in data:
    if predicate(x) and another_predicate(x):
        transformed = do_complex_transform(x)
        result.append(transformed)

# Never use a comprehension just for side effects!
# BAD:
[print(x) for x in range(5)]  # uses comprehension for side effect

# GOOD:
for x in range(5):
    print(x)

10. Dictionary Comprehensions

Same idea as list comprehensions, but creates dictionaries.

Python
# Basic dict comprehension
# Syntax: {key_expr: value_expr for item in iterable if condition}

# Squares as a dict
squares = {n: n**2 for n in range(6)}
print(squares)
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# Invert a dictionary
original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
print(inverted)
# {1: 'a', 2: 'b', 3: 'c'}

# Transform values
prices = {"apple": 1.20, "banana": 0.50, "cherry": 3.00}
discounted = {item: round(price * 0.9, 2) for item, price in prices.items()}
print(discounted)
# {'apple': 1.08, 'banana': 0.45, 'cherry': 2.7}

# Filter and transform
students = {"Alice": 92, "Bob": 45, "Charlie": 78, "Dave": 55}
passing = {name: score for name, score in students.items() if score >= 60}
print(passing)
# {'Alice': 92, 'Charlie': 78}

# Build a lookup from a list
words = ["hello", "world", "python"]
word_lengths = {word: len(word) for word in words}
print(word_lengths)
# {'hello': 5, 'world': 5, 'python': 6}

11. Generator Expressions

Generator expressions are like list comprehensions but they are lazy — they compute values one at a time and do not store everything in memory.

Python
# List comprehension — creates the full list in memory
squares_list = [n**2 for n in range(1_000_000)]  # 8+ MB

# Generator expression — computes on demand
squares_gen = (n**2 for n in range(1_000_000))   # tiny footprint

import sys
print(sys.getsizeof([n**2 for n in range(1000)]))   # ~8056 bytes
print(sys.getsizeof(n**2 for n in range(1000)))     # 104 bytes

# Use generators when you only need to iterate once
total = sum(n**2 for n in range(1000))
print(total)  # 332833500

# Find first match in a large sequence
first_big = next((n for n in range(1_000_000) if n**2 > 1000), None)
print(first_big)  # 32

# Generators are exhausted after one pass
gen = (x for x in range(5))
print(list(gen))  # [0, 1, 2, 3, 4]
print(list(gen))  # [] — exhausted!

12. Real Example: FizzBuzz

FizzBuzz is a classic programming interview exercise. Print numbers 1-100, but:

  • Print "Fizz" if divisible by 3
  • Print "Buzz" if divisible by 5
  • Print "FizzBuzz" if divisible by both
Python
def fizzbuzz(n):
    """Classic FizzBuzz up to n."""
    for i in range(1, n + 1):
        # Check 15 (3*5) FIRST, then 3, then 5
        if i % 15 == 0:
            print("FizzBuzz")
        elif i % 3 == 0:
            print("Fizz")
        elif i % 5 == 0:
            print("Buzz")
        else:
            print(i)

fizzbuzz(20)

# FizzBuzz using string concatenation (elegant variant)
def fizzbuzz_v2(n):
    for i in range(1, n + 1):
        result = ""
        if i % 3 == 0:
            result += "Fizz"
        if i % 5 == 0:
            result += "Buzz"
        print(result or i)

# FizzBuzz as a list comprehension (concise)
def fizzbuzz_v3(n):
    return [
        "FizzBuzz" if i % 15 == 0
        else "Fizz" if i % 3 == 0
        else "Buzz" if i % 5 == 0
        else i
        for i in range(1, n + 1)
    ]

result = fizzbuzz_v3(20)
print(result)
# [1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'FizzBuzz', 16, 17, 'Fizz', 19, 'Buzz']

13. Real Example: Number Guessing Game

Python
import random

def number_guessing_game():
    """
    A complete number guessing game demonstrating:
    - while loops
    - break/continue
    - if/elif/else
    - type conversion and input validation
    """
    SECRET = random.randint(1, 100)
    MAX_GUESSES = 7
    guesses_taken = 0
    
    print("=" * 40)
    print("  NUMBER GUESSING GAME")
    print(f"  I'm thinking of a number 1-100.")
    print(f"  You have {MAX_GUESSES} guesses.")
    print("=" * 40)
    
    while guesses_taken < MAX_GUESSES:
        remaining = MAX_GUESSES - guesses_taken
        
        # Input validation loop
        while True:
            raw = input(f"\nGuess ({remaining} remaining): ").strip()
            try:
                guess = int(raw)
                if 1 <= guess <= 100:
                    break
                else:
                    print("Please enter a number between 1 and 100.")
            except ValueError:
                print(f"'{raw}' is not a valid number.")
        
        guesses_taken += 1
        
        if guess == SECRET:
            print(f"\nāœ“ Correct! The number was {SECRET}.")
            print(f"  You got it in {guesses_taken} guess{'es' if guesses_taken > 1 else ''}!")
            break
        elif guess < SECRET:
            diff = SECRET - guess
            if diff > 20:
                print("Too low — way off!")
            elif diff > 5:
                print("Too low — getting warmer.")
            else:
                print("Too low — very close!")
        else:
            diff = guess - SECRET
            if diff > 20:
                print("Too high — way off!")
            elif diff > 5:
                print("Too high — getting warmer.")
            else:
                print("Too high — very close!")
    else:
        print(f"\nāœ— Out of guesses! The number was {SECRET}.")
    
    return guesses_taken

# Simulate a game (no real input)
# number_guessing_game()

# Demonstrate the logic with a mock
def simulate_game(secret, guesses):
    """Simulate a guessing game without interactive input."""
    print(f"Secret: {secret}")
    for guess in guesses:
        if guess == secret:
            print(f"Guess {guess}: Correct!")
            return True
        elif guess < secret:
            print(f"Guess {guess}: Too low")
        else:
            print(f"Guess {guess}: Too high")
    print("Out of guesses!")
    return False

simulate_game(42, [50, 25, 37, 44, 41, 43, 42])

14. Real Example: Prime Sieve (Sieve of Eratosthenes)

Finding all primes up to n using the classic algorithm:

Python
def sieve_of_eratosthenes(limit):
    """
    Find all prime numbers up to 'limit' using the Sieve of Eratosthenes.
    
    Algorithm:
    1. Start with all numbers 2..limit marked as prime
    2. For each prime p, mark all multiples of p (starting from p*p) as not prime
    3. Repeat until p*p > limit
    """
    if limit < 2:
        return []
    
    # Boolean array: is_prime[i] = True means i is prime
    is_prime = [True] * (limit + 1)
    is_prime[0] = False
    is_prime[1] = False
    
    # Only need to check up to sqrt(limit)
    p = 2
    while p * p <= limit:
        if is_prime[p]:
            # Mark all multiples of p as not prime
            # Start from p*p (smaller multiples already marked)
            for multiple in range(p * p, limit + 1, p):
                is_prime[multiple] = False
        p += 1
    
    # Collect primes
    primes = [n for n in range(2, limit + 1) if is_prime[n]]
    return primes

# Test it
primes_100 = sieve_of_eratosthenes(100)
print(f"Primes up to 100: {primes_100}")
print(f"Count: {len(primes_100)}")
# 25 primes up to 100

primes_1000 = sieve_of_eratosthenes(1000)
print(f"Primes up to 1000: {len(primes_1000)} primes")

# Verify: check if specific numbers are prime
def is_prime_check(n, primes_list):
    return n in primes_list

test_numbers = [2, 3, 4, 17, 25, 97, 100]
primes = set(sieve_of_eratosthenes(100))
for n in test_numbers:
    result = n in primes
    print(f"{n:3d} is {'prime' if result else 'not prime'}")

Alternative: Simple Primality Test

Python
def is_prime(n):
    """
    Check if n is prime using trial division.
    Time complexity: O(sqrt(n))
    """
    if n < 2:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    
    # Only check odd divisors up to sqrt(n)
    i = 3
    while i * i <= n:
        if n % i == 0:
            return False
        i += 2  # skip even numbers
    
    return True

# Test
for n in range(2, 30):
    if is_prime(n):
        print(n, end=" ")
# 2 3 5 7 11 13 17 19 23 29

# List comprehension with is_prime
primes = [n for n in range(2, 100) if is_prime(n)]
print(primes)

15. Performance Comparison

Understanding when to use each construct:

Python
import timeit

# Comparing sum approaches
n = 10000

# for loop with append
def sum_loop():
    result = []
    for i in range(n):
        result.append(i * i)
    return sum(result)

# list comprehension
def sum_comprehension():
    return sum([i * i for i in range(n)])

# generator expression
def sum_generator():
    return sum(i * i for i in range(n))

# Time each
loop_time = timeit.timeit(sum_loop, number=1000)
comp_time = timeit.timeit(sum_comprehension, number=1000)
gen_time = timeit.timeit(sum_generator, number=1000)

print(f"Loop:          {loop_time:.3f}s")
print(f"Comprehension: {comp_time:.3f}s")
print(f"Generator:     {gen_time:.3f}s")

# Typical results: comprehension ~2x faster than loop,
# generator slightly slower than comprehension but uses less memory

Key Takeaways

  1. elif, not else if — Python uses elif, not else if. Using else if creates a nested else block, which is a bug.
  2. Truthy/falsy simplifies conditions — if my_list: is cleaner than if len(my_list) > 0:.
  3. for/else and while/else are unique to Python — the else block runs only when no break was hit.
  4. break vs continue — break exits the loop entirely; continue skips to the next iteration.
  5. pass is a placeholder — use it when syntax requires a block but you have no code yet.
  6. range() is lazy — it does not create a list; it generates numbers on demand.
  7. List comprehensions are Pythonic — but use them only when the logic is simple and readable.
  8. Generator expressions save memory — use (expr for x in iter) when you only need to iterate once.
  9. Dict comprehensions — {k: v for k, v in ...} is the clean way to build dictionaries.
  10. Nested loops are O(n²) — be aware of performance with large datasets.

Common Mistakes

Python
# Mistake 1: Modifying a list while iterating over it
numbers = [1, 2, 3, 4, 5, 6]
for n in numbers:
    if n % 2 == 0:
        numbers.remove(n)    # BUG: skips elements!
print(numbers)  # [1, 3, 5] — BUT only by accident

# Correct: iterate over a copy or use comprehension
numbers = [1, 2, 3, 4, 5, 6]
numbers = [n for n in numbers if n % 2 != 0]
print(numbers)  # [1, 3, 5]

# Mistake 2: Off-by-one in range
# Want 1 to 10 inclusive
for i in range(1, 10):   # BUG: goes to 9
    pass
for i in range(1, 11):   # Correct: goes to 10
    pass

# Mistake 3: Using == instead of 'is' for None
result = None
if result == None:    # Works but not Pythonic
    pass
if result is None:    # Correct
    pass

# Mistake 4: Forgetting that dict iteration is over keys
scores = {"Alice": 95, "Bob": 87}
for item in scores:
    print(item)   # prints keys: Alice, Bob (not values!)

# Correct:
for name, score in scores.items():
    print(f"{name}: {score}")

# Mistake 5: Generator used twice
gen = (x for x in range(5))
print(list(gen))  # [0, 1, 2, 3, 4]
print(list(gen))  # [] — already exhausted!
# Use list if you need to iterate multiple times

Enjoyed this article?

Explore the Backend Systems learning path for more.

Found this helpful?

Share:š•

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.