Your code looks nice, seems to follow PEP 8 and has docstrings. I don't have much to say about it but here are a few changes to make it look more pythonic.
The while
loop can be rewritten using a for
loop with range
(or xrange
).
for divisor in xrange(5, 1+int(math.sqrt(n)), 6):
if n % divisor == 0 or n % (divisor + 2) == 0:
return False
return True
Then, this looks like a scenario where we could use all
/any
. The obvious way to convert the code above is :
return not any(n % divisor == 0 or n % (divisor + 2) == 0 for divisor in xrange(5, int(math.sqrt(n))+1, 6))
but it looks better (and makes more sense) to use all
with reversed conditions :
return all(n % divisor != 0 and n % (divisor + 2) != 0 for divisor in xrange(5, int(math.sqrt(n))+1, 6))
then, you can use the fact that non-zero numbers evaluates to True in a boolean context (and zero evaluates to False) :
return all(n % divisor and n % (divisor + 2) for divisor in xrange(5, int(math.sqrt(n))+1, 6))
Then, you could use the same kind of idea in the previous if
then merge duplicated code :
return n % 2 and n % 3 and all(n % divisor and n % (divisor + 2) for divisor in xrange(5, int(math.sqrt(n))+1, 6))
This is pretty much all I have to say about the code. Now, I think it might be worth commenting the algorithm a bit more.
def is_prime(n):
""" Check if n (assumed to be an int) is a prime number. """
# Handle values up to 3
if n < 2:
return False
if n in (2, 3):
return True
# Handles bigger values : divisors for n have to be
# * multiples of 2
# * multiples of 3
# * of the form 5 + 6*i or 5 + 6*i + 2 (other cases already handled)
return n % 2 and n % 3 and all(n % divisor and n % (divisor + 2) for divisor in xrange(5, int(math.sqrt(n))+1, 6))