Today we went from writing loops to writing list comprehensions, and used them on a real number-theory problem.
1. Quick Review
- Sequence types hold more than one value. Lists are mutable, tuples are not.
- Three ways to iterate:
whilefor index control,forfor items,enumeratefor both.
2. The range() Function
range(1, 10) # 1 to 9 — stop is EXCLUSIVE
list(range(1, 10)) # convert to see it
range(1, 101) # 1 to 100
range(1, 10, 3) # 1, 4, 7
range doesn’t return a list. It produces values on demand, so convert it to a list or tuple to look at it. Three parameters: start, stop, step — and to include 100 you stop at 101.
3. Reusing What We Built
from numeric_utils import is_prime
for n in range(1, 101):
if is_prime(n):
print(n)
That’s the point of last week’s module: write is_prime once, import it everywhere.
4. Returning a List Instead of Printing
def list_prime_numbers(start=1, end=10):
"""Return the prime numbers in a range."""
primes = []
for n in range(start, end + 1):
if is_prime(n):
primes.append(n)
return primes
sum(list_prime_numbers(100, 200))
Printing is a dead end; returning is reusable. Once the function hands you a list, sum() and everything else works on it. Functions can return lists, tuples, anything — use a tuple when the result shouldn’t be modified.
5. List Comprehensions
[expression for item in iterable if condition]
The expression and the loop are required; the condition is optional.
[n * 2 for n in range(1, 10)] # double everything
[n * 2 for n in range(1, 10) if n % 2 == 0] # double only the evens
sum([n for n in range(1, 10) if n % 3 == 0 or n % 5 == 0])
Read it right-to-left at first: loop, filter, then transform.
Where you’ll actually use it:
- Files in a folder over 2 MB
- Cart items from one particular brand
6. Factors and Prime Factors
A factor divides a number with no remainder. Every number has 1 and itself as factors; the interesting ones are the proper factors in between.
def factors(n):
"""Return the proper factors of n."""
return [i for i in range(2, n) if n % i == 0]
For 13195, that returns 14 numbers: 5, 7, 13, 29, 35, 65, 91, 145, 203, 377, 455, 1015, 1885, 2639.
Only four of them are prime — 5, 7, 13 and 29. So filter:
prime_factors = [f for f in factors(13195) if is_prime(f)]
7. Finding the Largest Prime Factor
The instinct from class was right — search from the top down — but with one trap. The largest divisor of 13195 is 2639, and 2639 is not prime (it’s 7 × 13 × 29). You need the largest divisor that’s also prime.
And a comprehension can’t stop early. It always builds the whole list. A generator expression can:
largest = next(
f for f in range(n - 1, 1, -1)
if n % f == 0 and is_prime(f)
)
next() pulls one value and stops there. That’s the tool for “find the first match and quit.”
One more speed-up: you only need to check factors up to √n, the same trick as in the prime checker.
✅ Homework
- Research
inandnot in— the membership operators. Be ready to explain them next class. - Practise comprehensions. Ask an AI for exercises at your level, then write them yourself.
- Try generating Google-style docstrings for your functions and compare them with what you’d write by hand.
