[英]using filter and generator to generator endless prime number in python
以下是我發現的使用Eratosthenes篩子查找素數的python程序。 它使用過濾器和生成器。 我聽不懂
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
def _not_divisible(n):
return lambda x: x % n > 0
def primes():
yield 2
it = _odd_iter()
while True:
n = next(it)
yield n
it = filter(_not_divisible(n), it)
for n in primes():
if n < 1000:
print(n)
else:
break
我不明白的是it = filter(_not_divisible(n), it)
。 例如,對於數字105,如何用單行代碼排除它?
這不只是一行代碼,它是被反復運行線,以不同的價值觀n
。
基本上, it
是一個迭代器,它產生尚未被篩子排除的候選質數。 您首先要使所有奇數都成為候選數。
it = _odd_iter()
然后,您反復選擇剩下的第一個候選人,
while True:
n = next(it)
刪除該候選人倍數的所有數字,
filter(_not_divisible(n), it)
並用刪除倍數后剩余的所有內容替換您的候選素數。
it = ...
如果您假裝filter
返回一個數字列表,而不是一個可迭代的列表,並且還假裝_odd_iter()
返回一個奇數列表而不是一個可迭代的列表,則可以遍歷循環並確定列表中每個點的內容。 例如,運行后
it = _odd_iter()
你開始
it = 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, ...
然后跑
n = next(it) # 3
這將第一件物品從前面拉下來,讓您
it = 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, ...
並運行
it = filter(_not_divisible(3), it)
過濾掉3的所有倍數,
it = 5, 7, 11, 13, 17, 19, 23, 25, ...
然后返回循環頂部,從前面拉出新的第一個數字
n = next(it) # 5
離開
it = 7, 11, 13, 17, 19, 23, 25, ...
然后濾除5的所有倍數
it = filter(_not_divisible(5), it)
這使
it = 7, 11, 13, 17, 19, 23, ...
等等。
實際上,由於filter()
返回的是迭代器,而不是列表,因此您最終會獲得嵌套的迭代器序列。 特別是,您從
it = _odd_iter()
然后在循環的第一次迭代之后
it = filter(_non_divisible(3), _odd_iter())
除了從迭代器中取出3
之外,然后在循環的第二次迭代之后
it = filter(_non_divisible(5), filter(_non_divisible(3), _odd_iter()))
除了從迭代器中也取了5
,然后
it = filter(_non_divisible(7), filter(_non_divisible(5), filter(_non_divisible(3), _odd_iter())))
等等。
對於找到的每個素數,將一個filter
應用於可迭代對象,所使用的過濾器是一項功能,它排除素數的所有倍數。
因此,您的可迭代項被包裹在與找到質數一樣多的過濾器中,例如,排除了數字105,因為它可以被3整除,並且在找到質數3時添加了3的所有倍數的過濾器。
如果添加一些print
語句,它將更加清晰(我希望):
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
def _not_divisible(n):
print('add filter for all multiples of', n)
return lambda x: print('check if', x, 'is divisible by', n, 'result: ', not (x % n > 0)) or x % n > 0
def primes():
yield 2
it = _odd_iter()
while True:
n = next(it)
yield n
it = filter(_not_divisible(n), it)
for n in primes():
if n < 20:
print(n)
else:
break
打印:
2
3
add filter for all multiples of 3
check if 5 is divisible by 3 result: False
5
add filter for all multiples of 5
check if 7 is divisible by 3 result: False
check if 7 is divisible by 5 result: False
7
add filter for all multiples of 7
check if 9 is divisible by 3 result: True
check if 11 is divisible by 3 result: False
check if 11 is divisible by 5 result: False
check if 11 is divisible by 7 result: False
11
add filter for all multiples of 11
check if 13 is divisible by 3 result: False
check if 13 is divisible by 5 result: False
check if 13 is divisible by 7 result: False
check if 13 is divisible by 11 result: False
13
add filter for all multiples of 13
check if 15 is divisible by 3 result: True
check if 17 is divisible by 3 result: False
check if 17 is divisible by 5 result: False
check if 17 is divisible by 7 result: False
check if 17 is divisible by 11 result: False
check if 17 is divisible by 13 result: False
17
add filter for all multiples of 17
check if 19 is divisible by 3 result: False
check if 19 is divisible by 5 result: False
check if 19 is divisible by 7 result: False
check if 19 is divisible by 11 result: False
check if 19 is divisible by 13 result: False
check if 19 is divisible by 17 result: False
19
add filter for all multiples of 19
check if 21 is divisible by 3 result: True
check if 23 is divisible by 3 result: False
check if 23 is divisible by 5 result: False
check if 23 is divisible by 7 result: False
check if 23 is divisible by 11 result: False
check if 23 is divisible by 13 result: False
check if 23 is divisible by 17 result: False
check if 23 is divisible by 19 result: False
首先,對迭代器進行過濾會返回另一個迭代器。 即當我們做類似的事情時:
it = filter(_not_divisible(3), it)
it = filter(_not_divisible(5), it)
我們得到一個鏈式迭代器“奇數且不能被3整除,不能被5整除”。 它在某種程度上類似於鏈式裝飾器,等效於:
# assuming we have decorator @not divisible
@not_divisible(2)
def iter():
return xrange(inf)
# then, at every subsequent prime we do something like:
iter = not_divisible(3)(iter)
# next prime is 5:
iter = not_divisible(5)(iter)
... 等等
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.