繁体   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