且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Python:生成器和过滤器如何在使用filter()生成素数列表的代码中工作

更新时间:2023-11-28 17:29:16

为更好地理解,我们也可以将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.