Python:生成器和过滤器如何在使用filter()生成素数列表的代码中工作 [英] Python: how does the generator and filter work in the codes generating prime list with filter()

查看:134
本文介绍了Python:生成器和过滤器如何在使用filter()生成素数列表的代码中工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意: 这个问题与使用过滤器和生成器来python中的生成器无穷素数,尽管它们都与Python代码有关,该代码找到了达到给定限制的所有素数.

Note: This question is different with using filter and generator to generator endless prime number in python although both of them are related to Python code finding all the prime numbers up to a given limit.

实际上,核心代码非常简单,但是我很难理解其工作原理.这就是我添加一些调试打印的原因.

The core codes are actually very simple, but it's hard for me to understand how it works. That's the reason I add some debug prints.

def _odd_number_generator():
    x = 1
    while True:
        x += 2
        print('    _odd_number_generator, x=', x)
        yield x

def _not_divisible(n):
    def func(x):
        print("      filter calling on x:", x, ", n:", n)
        return x % n > 0
    return func


def _primes():
    yield 2                                 # return first prime: 2
    odd_numbers = _odd_number_generator()   
    print("  in _primes, #a:  odd_numbers=", odd_numbers)
    while True:
        print("  in _primes, #b:         before next(filter) odd_numbers=", odd_numbers)

        # I know this line calling _odd_number_generator and _not_divisible, 
        # but how it works
        n = next(odd_numbers)   

        print("  in _primes, #c:         begin yield n:", n)
        yield n
        print("  in _primes, #d: n=", n, ", after yield  odd_numbers=", odd_numbers)
        odd_numbers = filter(_not_divisible(n), odd_numbers)    
        print("  in _primes, #e: n=", n, ", after filter odd_numbers=", odd_numbers)


def print_prime_numbes():
    for n in _primes():                                          
        print("  in print_prime_numbes, n = ", n)
        if n < 30:
            print(n)
            print()
            print("print_prime_numbes, begin next loop: n=", n)
        else:
            break

def test_print_prime_numbes():
    print("test_output_triangles() >>>")
    print_prime_numbes()

使用过滤器和生成器的答案在python中使用无穷素数生成器有助于理解链式迭代器.但是,我仍然难以理解_odd_number_generator和 处理数字25时会调用_not_divisible.

The answer in using filter and generator to generator endless prime number in python is very helpful to understand the chained iterator. But still, I get problem to understand how the _odd_number_generator and _not_divisible is being called when handling the number 25.

例如,这是运行时的一段输出:

For example, here is a piece of outputs when running:

print_prime_numbes, begin next loop: n= 23
  in _primes, #d: n= 23 , after yield  odd_numbers= <filter object at 0x000002B0E02366D8>
  in _primes, #e: n= 23 , after filter odd_numbers= <filter object at 0x000002B0E0236F98>
  in _primes, #b:         before next(filter) odd_numbers= <filter object at 0x000002B0E0236F98>
    _odd_number_generator, x= 25
      filter calling on x: 25 , n: 3
      filter calling on x: 25 , n: 5
    _odd_number_generator, x= 27
      filter calling on x: 27 , n: 3
    _odd_number_generator, x= 29
      filter calling on x: 29 , n: 3
      filter calling on x: 29 , n: 5
      filter calling on x: 29 , n: 7
      filter calling on x: 29 , n: 11
      filter calling on x: 29 , n: 13
      filter calling on x: 29 , n: 17
      filter calling on x: 29 , n: 19
      filter calling on x: 29 , n: 23
  in _primes, #c:         begin yield n: 29
  in print_prime_numbes, n =  29
29

在这里,由于25是可整除的,因此正在生成下一个数字27.我想知道是什么使通话产生27?

Here, because 25 is divisible, next number, 27, is being generated. I want to know what makes the calling to generate 27?

[已编辑]

在yield 23之后,进入下一个循环,odd_numbers应该是这样的: filter(_not_divisible(23),filter(_not_divisible(19)... filter(_not_divisible(7),filter(_not_divisible(5),filter(_not_divisible(5),filter(_not_divisible(3),_ odd_generator()))).

After yield 23, and go to next loop, the odd_numbers should be something like this: filter(_not_divisible(23),filter(_not_divisible(19) ...filter(_not_divisible(7),filter(_not_divisible(5),filter(_not_divisible(5),filter(_not_divisible(3), _odd_generator())).

运行"yield n"时,将生成下一个数字25并检查可除性,并且_not_divisible返回False.在这里,看起来像'yield'接下来将在_odd_generator()上运行,并检查是否可以将新数字除以3、4、5,.. 23直到得到素数.但我想在这里详细了解该机制.

When running "yield n", the next number 25, is being generated and check the divisibility, and _not_divisible return False. Here, looks like the 'yield' will run next on _odd_generator() and check if the new number can be divided by 3,4,5,..23 until it gets a prime. But I want to know the mechanism here in details.

推荐答案

为更好地理解,我们也可以将filter视为生成器:

For better understanding, we can look at filter as a generator as well:

def filter(condition, iterable):
    for value in iterable:      # 1. consume values from `iterable`
        if condition(value):    # 2. test `condition` for `value`
            yield value         # 3. yield any valid `value`

换句话说,odd_numbers = filter(_not_divisible(n), odd_numbers)是包装另一个生成器(_odd_number_generator)的生成器(filter).对于每个素数,新的filter会包裹在现有包装的过滤器周围.查看最初的情况之一,我们有以下设置:

In other words, odd_numbers = filter(_not_divisible(n), odd_numbers) is a generator (filter) wrapping another generator (_odd_number_generator). For every prime number, a new filter is wrapped around the existing wrapped filters. Looking at one of the initial cases, we have this setup:

odd_numbers = filter(_not_divisible(n=7),  # <filter A>
    filter(_not_divisible(n=5),            # <filter B>
        filter(_not_divisible(n=3),        # <filter C>
            _odd_number_generator()        # <odd_numbers @ x=7>
))

现在,如果我们叫next(odd_numbers)会发生什么?

Now, what happens if we call next(odd_numbers)?

  • <filter A>:1通过调用next(<filter B>)来获取value
    • <filter B>:1通过调用next(<filter C>)来获取value
      • <filter C>:1通过调用next(<odd_numbers @ x=7>)来获取value
        • <odd_numbers @ x=7>x+=2递增到x=9并产生
        • <filter A>:1 fetches a value by calling next(<filter B>)
          • <filter B>:1 fetches a value by calling next(<filter C>)
            • <filter C>:1 fetches a value by calling next(<odd_numbers @ x=7>)
              • <odd_numbers @ x=7> increments x+=2 to x=9 and yields it
              • <odd_numbers @ x=9>x+=2递增到x=11并产生
              • <odd_numbers @ x=9> increments x+=2 to x=11 and yields it

              重要的部分是_not_divisible(n=3)不允许值9通过.取而代之的是,<filter C>中的循环获取另一个值而没有产生<filter B><filter A>.

              The important part is that _not_divisible(n=3) does not let the value 9 pass. Instead, the loop in <filter C> fetches another value without yielding to <filter B> and <filter A>.

              随着_odd_number_generator()周围包裹着越来越多的filter(_not_divibible(n), ...)层,还有另外一些层可以执行跳过yield并请求新的value"".中间生成器可以在屈服之前消耗几个值的一般原理保持不变.

              As more and more filter(_not_divibible(n), ...) layers are wrapped around _odd_number_generator(), there are additional layers which do the "skip yield and request new value". The general principle, that an intermediate generator can consume several values before yielding, remains the same.

              这篇关于Python:生成器和过滤器如何在使用filter()生成素数列表的代码中工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆