簡體   English   中英

使用過濾器和生成器在python中生成無窮素數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM