Python Recap II — Prime Numbers
Start here Prime numbers are a great playground for Python. With them we revise functions,
forandwhileloops,break, multiple assignment and dictionaries. We also see how one small idea (checking only up to √n) makes a program much faster.
What is a prime?
A prime number has exactly two factors: 1 and itself.
| n | Factors | Exactly two? | Prime? |
|---|---|---|---|
| 1 | 1 | No (only one factor) | No — 1 is NOT prime |
| 2 | 1, 2 | Yes | Yes (the only even prime) |
| 7 | 1, 7 | Yes | Yes |
| 12 | 1, 2, 3, 4, 6, 12 | No | No |
Method 1 — make the list of factors
Step 1: write a function that returns all factors of n.
def factors(n):
fl = [] # factor list
for i in range(1, n + 1):
if (n % i) == 0:
fl.append(i)
return flfactors(12) → [1, 2, 3, 4, 6, 12]
Step 2: n is prime if its factor list is exactly [1, n].
def prime(n):
return factors(n) == [1, n]prime(7)→factors(7)is[1, 7]→ equals[1, 7]→ Trueprime(1)→factors(1)is[1]→ not equal to[1, 1]→ False ✔ (so 1 is correctly not prime)
Listing primes
All primes up to m — use `for`
We know exactly how many numbers to check (1 to m), so a for loop fits.
def primesupto(m):
pl = [] # prime list
for i in range(1, m + 1):
if prime(i):
pl.append(i)
return plprimesupto(30) → [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
The first m primes — use `while`
Now we don't know how far to go. To get the first 10 primes, do we check up to 30? 50? We can't say in advance. So we use while and keep going until we have collected m primes.
def firstprimes(m):
(count, i, pl) = (0, 1, []) # three assignments in one line
while (count < m):
if prime(i):
(count, pl) = (count + 1, pl + [i])
i = i + 1 # move to the next number — never forget!
return plfirstprimes(10) → [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Multiple (simultaneous) assignment: (count, i, pl) = (0, 1, []) sets count = 0, i = 1, pl = [] all at once.
for or while? — the rule
| Use | When | Example |
|---|---|---|
for | You know how many rounds in advance | Check every number from 1 to m |
while | You don't know; you stop when a condition becomes false | Keep going till you find m primes |
Big danger with while: something inside the loop must make progress towards stopping. In firstprimes, i = i + 1 moves us forward. Remove it, and the loop runs forever.

Method 2 — look for a factor directly
We don't need the whole factor list. n is prime if no number from 2 to n − 1 divides it.
def prime(n):
result = True
for i in range(2, n):
if (n % i) == 0:
result = False
break # found a factor — stop checking
return resultbreak jumps out of the loop at once. If 2 divides 1000, why check 3, 4, ..., 999? Stop immediately.
The same thing using while (the condition itself stops the loop when result becomes False):
def prime(n):
(result, i) = (True, 2)
while (result and (i < n)):
if (n % i) == 0:
result = False
i = i + 1
return resultMethod 3 — check only up to √n (faster)
Key idea: factors come in pairs. If a × b = n, then one of a, b is at most √n and the other is at least √n.
Look at n = 36 (√36 = 6):
| Pair | Small one (≤ 6) | Big one (≥ 6) |
|---|---|---|
| 1 × 36 | 1 | 36 |
| 2 × 18 | 2 | 18 |
| 3 × 12 | 3 | 12 |
| 4 × 9 | 4 | 9 |
| 6 × 6 | 6 | 6 |
So if n has any factor other than 1 and itself, it has one that is ≤ √n. We can stop checking at √n.

import math
def prime(n):
(result, i) = (True, 2)
while (result and (i <= math.sqrt(n))):
if (n % i) == 0:
result = False
i = i + 1
return resultHow much faster? For n = 97: Method 2 checks 2, 3, ..., 96 → 95 numbers. Method 3 checks only 2 to 9 (√97 ≈ 9.85) → 8 numbers.
Careful — a small bug in Methods 2 and 3. For
n = 1, the loop never runs (there is no number from 2 to 0, and 2 > √1), so they return True — saying 1 is prime, which is wrong! Method 1 gets it right. A safe fix is to add this line at the start:if n < 2: return False.
How are primes spread out?
- There are infinitely many primes. (Proved over 2000 years ago by Euclid.)
- Twin primes are two primes with a gap of 2: (3, 5), (5, 7), (11, 13), (17, 19), (29, 31)...
- Twin prime conjecture: there are infinitely many twin primes. Nobody has proved it yet — it is still an open problem!

Counting the gaps between primes — using a dictionary
Let us count how often each gap appears. We start from 3, because 2 is the smallest prime and we use it as the first lastprime.
def primediffs(n):
lastprime = 2
pd = {} # dictionary: gap -> how many times
for i in range(3, n + 1):
if prime(i):
d = i - lastprime
lastprime = i
if d in pd.keys():
pd[d] = pd[d] + 1 # seen this gap before: add 1
else:
pd[d] = 1 # new gap: start counting at 1
return pdTrace for primediffs(30) (primes 2, 3, 5, 7, 11, 13, 17, 19, 23, 29):
| Prime | Gap from last prime | pd after this step |
|---|---|---|
| 3 | 3 − 2 = 1 | {1: 1} |
| 5 | 5 − 3 = 2 | {1: 1, 2: 1} |
| 7 | 2 | {1: 1, 2: 2} |
| 11 | 4 | {1: 1, 2: 2, 4: 1} |
| 13 | 2 | {1: 1, 2: 3, 4: 1} |
| 17 | 4 | {1: 1, 2: 3, 4: 2} |
| 19 | 2 | {1: 1, 2: 4, 4: 2} |
| 23 | 4 | {1: 1, 2: 4, 4: 3} |
| 29 | 6 | {1: 1, 2: 4, 4: 3, 6: 1} |
Answer: {1: 1, 2: 4, 4: 3, 6: 1} — the gap 2 (twin primes) appeared 4 times.
In one line: A prime has exactly two factors; check for a factor only up to √n, use for when the count is known and while when it isn't.
Exam words: prime, factor, break, for vs while, multiple assignment, √n check, twin primes, dictionary (d in pd.keys()).
Quick check
1. Is 1 a prime? Why?
No. A prime needs exactly two factors; 1 has only one factor.2. To test if 101 is prime using the √n method, up to which number do we check?
√101 ≈ 10.05, so we check 2 to 10.3. What happens if you forget i = i + 1 in firstprimes?
i never changes, so the loop never ends (infinite loop).4. What does (a, b) = (b, a) do?
Swaps the values of a and b in one step.5. What does the Method 2 code (with range(2, n)) return for n = 1? Is that right?
It returns True, because the loop never runs. That is wrong — 1 is not prime. Add if n < 2: return False.