Everything holroy said, about choice of algorithm especially. Also: 1. Skip numbers more quickly: `lower = max(lower, 2)` before you enter the loop will not only save you the iterations for negative numbers, but will also let you remove the `if num > 1` test that's inside the loop, for savings _no matter the input_. 2. Move as much as possible outside the loop: `n == 2` is only going to happen once, so do it beforehand to save an 'inside the loop' operation. 3. You only need to test up to `sqrt(num)`. (but, per above, avoid computing it more than once) 2. When I went to write my own version of this, I found myself replacing your: for i in range(2, num): if (num % i) == 0: break else: total += num list_of_primes.append(num) with: is_prime = not any(num % i == 0 for i in range(2, num)) if is_prime: total += num list_of_primes.append(num) So, using both of those, your loop looks like: list_of_primes = [] # test 2 beforehand for speed if lower <= 2 <= upper: total += 2 list_of_primes.append(2) # no sense looking for primes below 3 range_lower = max(lower, 3) # the largest factor we need to test is sqrt(num) max_factor = int(num**0.5) for num in range(range_lower, upper + 1): if not any(num % i == 0 for i in range(2, max_factor)): total += num list_of_primes.append(num)