我有一个家庭作业要编写一个素数生成器
I have a homework assignment to program a prime number generator
关于求助的作业规则如下:
如果我对自己的代码感到困惑,并且无法复制和粘贴其他人的代码,我可以寻求帮助。我必须了解所有代码,以及每个功能和代码片段的作用。我们了解了 next 函数,我们必须使用 class 来制作生成器。我们还了解了 StopIteration,但我什么时候使用它呢?当我使用它时,我的代码似乎无法正常工作。可能是我放错地方了。
我在结束生成器时遇到了一些麻烦,当数字不是质数时它也一直返回 None,当我希望它继续运行而不是下一个质数时。我怎样才能让它结束,并且一直持续到它到达下一个素数而不是返回 None?
这是我到目前为止尝试过的:
class PrimeGenerator:
def __init__(self, maximum):
self.maximum = maximum + 1
self.count = 0
def __next__(self):
if self.count < self.maximum:
for num in range(self.count, self.maximum):
for divisor in range(2, self.count + 1):
if num // divisor != num / divisor:
print(f'number is prime, it is {num} and the count is {self.count}, and the divisor is {divisor}')
self.count += 1
return num
else:
break
self.count += 1
my_gen = PrimeGenerator(7)
print(next(my_gen))
print(next(my_gen))
print(next(my_gen))
print(next(my_gen))
print(next(my_gen))
如有任何帮助,我们将不胜感激。
您实现的是“迭代器”,而不是真正的“生成器”。根据 Python 文档:
Python provides generator functions as a convenient shortcut to
building iterators. Generator functions allow you to declare a
function that behaves like an iterator, i.e. it can be used in a for
loop.
def PrimeGenerator(maximum):
for num in range(2, maximum + 1):
for divisor in range(2, num):
if num // divisor == num / divisor:
break
else:
yield num
for p in PrimeGenerator(7):
print(p)
结果:
2
3
5
7
为了完整起见,并展示使用真正的生成器可以节省多少代码,这里是与经典迭代器相同的逻辑:
class PrimeGenerator:
def __init__(self, highest):
self.next_candidate = 2
self.highest_number = highest
def __iter__(self):
return self
def __next__(self):
for num in range(self.next_candidate, self.highest_number + 1):
for divisor in range(2, num // 2 + 1):
if num // divisor == num / divisor:
break
else:
self.next_candidate = num + 1
return num
raise StopIteration
def next(self):
return self.__next__()
for p in PrimeGenerator(7):
print(p)
为了确保它有效,我还尝试使用在迭代器上调用 next() 的模式。这给出了相同的结果:
p = PrimeGenerator(7)
while True:
try:
print(p.next())
except StopIteration:
break
在class的构造函数中,定义当前数和最大数。拥有最高数的意义在于,当我们遇到一个大于最高数的数时,我们就结束了我们的素数生成。为此,我们提出了一个 StopIteration
异常。
在__next__
方法中,我们检查数字是否为质数。如果是,我们 return 否则我们前进到下一个并重复该过程。
def is_prime(n):
if n == 2:
return True
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
class PrimeGenerator:
def __init__(self, highest=100):
self.current = 2
self.highest_number = highest
def __iter__(self):
return self
def __next__(self):
while True:
if self.current > self.highest_number:
raise StopIteration
if is_prime(self.current):
self.current += 1
return self.current - 1
self.current += 1
prime_generator = PrimeGenerator(10)
print(next(prime_generator))
print(next(prime_generator))
print(next(prime_generator))
print(next(prime_generator))
print(next(prime_generator))
# For large maximum values
for prime in PrimeGenerator(100):
print(prime)
为了停止生成器,您所要做的就是在函数末尾引发 StopIteration。
我认为您的代码的素数查找逻辑是错误的,因此我编写了自己的素数测试。每次调用 __next__
时,它都会继续测试 count 中的整数,如果它们是质数则返回。我们只需要循环到 sqrt(num) 来检查它是否是素数,因为任何高于 sqrt(num) 的因子都会有一个更小的对应因子。您还可以使用模运算符轻松检查因子,而不是除法。
我还添加了 __iter__
以便生成器可以在 for 循环中使用。
class PrimeGenerator:
def __init__(self, maximum):
self.maximum = maximum
self.count = 2
def __iter__(self):
return self
def __next__(self):
while self.count <= self.maximum:
num = self.count
is_prime = True
for divisor in range(2, 1 + int(num ** 0.5)):
if self.count % divisor == 0:
is_prime = False
break
if is_prime:
self.count += 1
return num
self.count += 1
raise StopIteration()
您的问题和随后的评论让您不清楚 maximum
的含义。 IE。素数生成器应该产生的素数,或者它应该考虑的最大素数。首先让我们考虑它限制了产生的素数数量:
class PrimeGenerator:
def __init__(self, maximum):
self.maximum = maximum # how many primes we'll generate
self.count = 0 # how many primes we've generated
self.number = 1 # prime the prime pump
def __iter__(self):
return self
def __next__(self):
if self.count < self.maximum:
if self.count == 0: # for speed, treat 2 as a special case
self.count += 1
return 2
while True:
self.number += 2
for divisor in range(3, int(self.number ** 0.5) + 1, 2):
if self.number % divisor == 0:
break
else: # no break 'for'
self.count += 1
return self.number # found a prime
raise StopIteration() # exceeded maximum
if __name__ == '__main__':
generator = PrimeGenerator(25)
while True:
try:
print(next(generator), end=" ")
except StopIteration:
print()
break
现在让我们修改代码,使 maximum
参数代表考虑的 最大 数字:
class PrimeGenerator:
def __init__(self, maximum):
self.maximum = maximum # largest number we'll consider
self.number = 2 # prime the prime pump
def __iter__(self):
return self
def __next__(self):
if self.number <= self.maximum:
if self.number == 2: # for speed, treat 2 as a special case
self.number += 1
return 2
while self.number < self.maximum:
for divisor in range(3, int(self.number ** 0.5) + 1, 2):
if self.number % divisor == 0:
break
else: # no break 'for'
prime = self.number
self.number += 2
return prime # found a prime
self.number += 2
raise StopIteration() # exceeded maximum
这些示例将 2 视为特例,随后像其他示例一样避免将偶数作为候选 and/or 除数。 (这样做的好处是速度提高了约 4 倍。)
关于求助的作业规则如下: 如果我对自己的代码感到困惑,并且无法复制和粘贴其他人的代码,我可以寻求帮助。我必须了解所有代码,以及每个功能和代码片段的作用。我们了解了 next 函数,我们必须使用 class 来制作生成器。我们还了解了 StopIteration,但我什么时候使用它呢?当我使用它时,我的代码似乎无法正常工作。可能是我放错地方了。
我在结束生成器时遇到了一些麻烦,当数字不是质数时它也一直返回 None,当我希望它继续运行而不是下一个质数时。我怎样才能让它结束,并且一直持续到它到达下一个素数而不是返回 None? 这是我到目前为止尝试过的:
class PrimeGenerator:
def __init__(self, maximum):
self.maximum = maximum + 1
self.count = 0
def __next__(self):
if self.count < self.maximum:
for num in range(self.count, self.maximum):
for divisor in range(2, self.count + 1):
if num // divisor != num / divisor:
print(f'number is prime, it is {num} and the count is {self.count}, and the divisor is {divisor}')
self.count += 1
return num
else:
break
self.count += 1
my_gen = PrimeGenerator(7)
print(next(my_gen))
print(next(my_gen))
print(next(my_gen))
print(next(my_gen))
print(next(my_gen))
如有任何帮助,我们将不胜感激。
您实现的是“迭代器”,而不是真正的“生成器”。根据 Python 文档:
Python provides generator functions as a convenient shortcut to building iterators. Generator functions allow you to declare a function that behaves like an iterator, i.e. it can be used in a for loop.
def PrimeGenerator(maximum):
for num in range(2, maximum + 1):
for divisor in range(2, num):
if num // divisor == num / divisor:
break
else:
yield num
for p in PrimeGenerator(7):
print(p)
结果:
2
3
5
7
为了完整起见,并展示使用真正的生成器可以节省多少代码,这里是与经典迭代器相同的逻辑:
class PrimeGenerator:
def __init__(self, highest):
self.next_candidate = 2
self.highest_number = highest
def __iter__(self):
return self
def __next__(self):
for num in range(self.next_candidate, self.highest_number + 1):
for divisor in range(2, num // 2 + 1):
if num // divisor == num / divisor:
break
else:
self.next_candidate = num + 1
return num
raise StopIteration
def next(self):
return self.__next__()
for p in PrimeGenerator(7):
print(p)
为了确保它有效,我还尝试使用在迭代器上调用 next() 的模式。这给出了相同的结果:
p = PrimeGenerator(7)
while True:
try:
print(p.next())
except StopIteration:
break
在class的构造函数中,定义当前数和最大数。拥有最高数的意义在于,当我们遇到一个大于最高数的数时,我们就结束了我们的素数生成。为此,我们提出了一个 StopIteration
异常。
在__next__
方法中,我们检查数字是否为质数。如果是,我们 return 否则我们前进到下一个并重复该过程。
def is_prime(n):
if n == 2:
return True
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
class PrimeGenerator:
def __init__(self, highest=100):
self.current = 2
self.highest_number = highest
def __iter__(self):
return self
def __next__(self):
while True:
if self.current > self.highest_number:
raise StopIteration
if is_prime(self.current):
self.current += 1
return self.current - 1
self.current += 1
prime_generator = PrimeGenerator(10)
print(next(prime_generator))
print(next(prime_generator))
print(next(prime_generator))
print(next(prime_generator))
print(next(prime_generator))
# For large maximum values
for prime in PrimeGenerator(100):
print(prime)
为了停止生成器,您所要做的就是在函数末尾引发 StopIteration。
我认为您的代码的素数查找逻辑是错误的,因此我编写了自己的素数测试。每次调用 __next__
时,它都会继续测试 count 中的整数,如果它们是质数则返回。我们只需要循环到 sqrt(num) 来检查它是否是素数,因为任何高于 sqrt(num) 的因子都会有一个更小的对应因子。您还可以使用模运算符轻松检查因子,而不是除法。
我还添加了 __iter__
以便生成器可以在 for 循环中使用。
class PrimeGenerator:
def __init__(self, maximum):
self.maximum = maximum
self.count = 2
def __iter__(self):
return self
def __next__(self):
while self.count <= self.maximum:
num = self.count
is_prime = True
for divisor in range(2, 1 + int(num ** 0.5)):
if self.count % divisor == 0:
is_prime = False
break
if is_prime:
self.count += 1
return num
self.count += 1
raise StopIteration()
您的问题和随后的评论让您不清楚 maximum
的含义。 IE。素数生成器应该产生的素数,或者它应该考虑的最大素数。首先让我们考虑它限制了产生的素数数量:
class PrimeGenerator:
def __init__(self, maximum):
self.maximum = maximum # how many primes we'll generate
self.count = 0 # how many primes we've generated
self.number = 1 # prime the prime pump
def __iter__(self):
return self
def __next__(self):
if self.count < self.maximum:
if self.count == 0: # for speed, treat 2 as a special case
self.count += 1
return 2
while True:
self.number += 2
for divisor in range(3, int(self.number ** 0.5) + 1, 2):
if self.number % divisor == 0:
break
else: # no break 'for'
self.count += 1
return self.number # found a prime
raise StopIteration() # exceeded maximum
if __name__ == '__main__':
generator = PrimeGenerator(25)
while True:
try:
print(next(generator), end=" ")
except StopIteration:
print()
break
现在让我们修改代码,使 maximum
参数代表考虑的 最大 数字:
class PrimeGenerator:
def __init__(self, maximum):
self.maximum = maximum # largest number we'll consider
self.number = 2 # prime the prime pump
def __iter__(self):
return self
def __next__(self):
if self.number <= self.maximum:
if self.number == 2: # for speed, treat 2 as a special case
self.number += 1
return 2
while self.number < self.maximum:
for divisor in range(3, int(self.number ** 0.5) + 1, 2):
if self.number % divisor == 0:
break
else: # no break 'for'
prime = self.number
self.number += 2
return prime # found a prime
self.number += 2
raise StopIteration() # exceeded maximum
这些示例将 2 视为特例,随后像其他示例一样避免将偶数作为候选 and/or 除数。 (这样做的好处是速度提高了约 4 倍。)