简体   繁体   English

使用过滤器和生成器在python中生成无穷素数

[英]using filter and generator to generator endless prime number in python

Below is a python program I found to find prime numbers using Sieve of Eratosthenes . 以下是我发现的使用Eratosthenes筛子查找素数的python程序。 It uses filter and generator. 它使用过滤器和生成器。 I'm not able to understand it. 我听不懂

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

What I don't understand is it = filter(_not_divisible(n), it) . 我不明白的是it = filter(_not_divisible(n), it) For example for number 105, how is it excluded by this single line of code? 例如,对于数字105,如何用单行代码排除它?

It's not just that single line of code, it's that line being run repeatedly, with different values of n . 这不只是一行代码,它是被反复运行线,以不同的价值观n

Basically, it is an iterator that yields candidate prime numbers which have not yet been ruled out by the sieve. 基本上, it是一个迭代器,它产生尚未被筛子排除的候选质数。 You start by making all odd numbers candidates. 您首先要使所有奇数都成为候选数。

it = _odd_iter()

Then you repeatedly take the first remaining candidate, 然后,您反复选择剩下的第一个候选人,

while True:
    n = next(it)

remove all numbers that are multiples of that candidate, 删除该候选人倍数的所有数字,

    filter(_not_divisible(n), it)

and replace your candidate primes with everything that is left after removing multiples. 并用删除倍数后剩余的所有内容替换您的候选素数。

    it = ...

If you pretend filter returns a list of numbers, rather than an iterable, and also pretend _odd_iter() returns a list of odd numbers instead of an iterable, you can trace through the loop and determine what's in the list at each point. 如果您假装filter返回一个数字列表,而不是一个可迭代的列表,并且还假装_odd_iter()返回一个奇数列表而不是一个可迭代的列表,则可以遍历循环并确定列表中每个点的内容。 For example, after running 例如,运行后

it = _odd_iter()

you start with 你开始

it = 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, ...

Then run 然后跑

    n = next(it) # 3

which pulls the first item off the front, leaving you with 这将第一件物品从前面拉下来,让您

it = 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, ...

and run 并运行

    it = filter(_not_divisible(3), it)

filter out all the multiples of 3, 过滤掉3的所有倍数,

it = 5, 7, 11, 13, 17, 19, 23, 25, ...

Then go back to the top of the loop and pull the new first number off the front 然后返回循环顶部,从前面拉出新的第一个数字

    n = next(it) # 5

leaving 离开

it = 7, 11, 13, 17, 19, 23, 25, ...

and then filter out all the multiples of 5, 然后滤除5的所有倍数

    it = filter(_not_divisible(5), it)

which gives 这使

it = 7, 11, 13, 17, 19, 23, ...

and so on. 等等。

In practice, because filter() returns an iterator, not a list, you wind up getting a nested sequence of iterators. 实际上,由于filter()返回的是迭代器,而不是列表,因此您最终会获得嵌套的迭代器序列。 In particular, you start with 特别是,您从

it = _odd_iter()

then after the first iteration of the loop, you have basically 然后在循环的第一次迭代之后

it = filter(_non_divisible(3), _odd_iter())

except that 3 has been taken from the iterator, and then after the second iteration of the loop you have 除了从迭代器中取出3之外,然后在循环的第二次迭代之后

it = filter(_non_divisible(5), filter(_non_divisible(3), _odd_iter()))

except that 5 has also been taken from the iterator, and then 除了从迭代器中也取了5 ,然后

it = filter(_non_divisible(7), filter(_non_divisible(5), filter(_non_divisible(3), _odd_iter())))

and so on. 等等。

For each prime number found a filter is applied to the iterable, the filter used is a function that excludes all multiples of the prime number. 对于找到的每个素数,将一个filter应用于可迭代对象,所使用的过滤器是一项功能,它排除素数的所有倍数。

So your iterable is wrapped in as many filters as you found prime numbers, for example the number 105 is excluded because it's divisible by 3 and the filter for all multiples of 3 was added when you found the prime number 3. 因此,您的可迭代项被包裹在与找到质数一样多的过滤器中,例如,排除了数字105,因为它可以被3整除,并且在找到质数3时添加了3的所有倍数的过滤器。

If you add some print statements it will be a bit clearer (I hope): 如果添加一些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

which prints: 打印:

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

First, filter over iterator returns another iterator. 首先,对迭代器进行过滤会返回另一个迭代器。 Ie when we do something like: 即当我们做类似的事情时:

it = filter(_not_divisible(3), it)
it = filter(_not_divisible(5), it)

We get a chained iterator "odd number AND not divisible by 3 AND not divisible by 5". 我们得到一个链式迭代器“奇数且不能被3整除,不能被5整除”。 It is somewhat similar to chained decorators, where we get an equivalent of: 它在某种程度上类似于链式装饰器,等效于:

# 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)

... and so on ... 等等

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM