The first mistake is here:
n = NextPrime
Are you saying that n
will receive its own class NextPrime
, and not an instance of it. To instantiate the class you should use parentheses:
n = NextPrime()
But that alone is not enough. The documentation describes how to create an iterator, but in summary, there are two methods that should be implemented as follows:
__iter__
: returns the iterator object itself. That is, it must return self
, and not 1
as you did
__next__
: returns the next value (or throws an exception StopIteration
if there are no more values to return)
Both methods do not receive any parameter (only the self
, clear-cut).
Another detail is that when the number is 4, your code enters loop infinite (see). So let’s change this algorithm.
The for
don’t need to go up to the number, can go to its square root. And with the exception of 2 and 3, all other prime numbers are in the form 6k - 1
or 6k + 1
(that is, are predecessors or successors of a multiple of 6), so I can make a loop that only tests these cases. Remember also that 2 is the only even number that is prime, all other primes are odd, so from 3 I can add 2 to the current number (testing the pairs is a waste of time).
Then it would look like this:
from math import sqrt
class NextPrime:
def __init__(self):
self.num = 1 # todos começam em 1
def __iter__(self):
return self # retorna o próprio objeto, não o valor
def __next__(self):
if self.num in (1, 2): # se for 1 ou 2, o próximo número (2 ou 3) com certeza é primo
self.num += 1
return self.num
# aqui eu já sei que "num" é pelo menos 3
while True:
self.num += 2 # somo 2, pois não preciso testar números pares
if self.num % 3 != 0: # se for divisível 3, nem testa o número
# não é múltiplo de 3, testar se é divisor de 6k - 1 ou 6k + 1
for i in range(5, int(sqrt(self.num)) + 1, 6):
if self.num % i == 0 or self.num % (i + 2) == 0:
break # não é primo, testa o próximo
else: # é primo, interrompe o while
break
return self.num
n = NextPrime()
# imprime os 100 primeiros números primos
for _ in range(100):
print(next(n))
Remembering that this iterator is infinite, because we do not define a stop condition (could have a maximum limit, and launch the StopIteration
case self.num
exceed this limit, for example). That is to say, nay do for i in n
, but will go into loop infinite.
Another detail is that the first cousin returned is 2, since number 1 is not prime.
Another way to do it would be to create a Generator:
from math import sqrt
def next_prime(start = 1):
num = start
if num == 1:
num += 1
yield num
if num == 2:
num += 1
yield num
while True:
num += 2 # somo 2, pois não preciso testar números pares
if num % 3 != 0: # se for divisível 3, nem testa o número
# não é múltiplo de 3, testar se é divisor de 6k - 1 ou 6k + 1
for i in range(5, int(sqrt(num)) + 1, 6):
if num % i == 0 or num % (i + 2) == 0:
break # não é primo, testa o próximo
else: # é primo, retorna
yield num
n = next_prime()
# imprime os 100 primeiros números primos
for _ in range(100):
print(next(n))
you defined
next
as a method and is trying to use as a function?– Lucas