如何在reduce函数中使用python生成器?

时间:2017-12-13 02:35:01

标签: python generator reduce

有人可以帮我理解这段代码的执行情况吗?

from functools import reduce

def foo():
    for i in range(10):
        yield i

gen = foo()

print (gen == 0, gen.__next__ == 0, gen.__next__ == 1, reduce(lambda a,b:a+b, gen))

我的问题如下:

  • 有多个打印参数在做什么? gen == 0是什么意思?那不是生成器对象吗?
  • 另外,reduce函数如何记住分配给a和b的内容?
  • 调用gen = foo()之后,执行只是在函数和reduce语句之间切换吗?

如果有人能够确定发电机的功能和减少功能,那将有很大帮助!谢谢!

1 个答案:

答案 0 :(得分:2)

如您所知,gen是一个发电机; print中的所有测试都是荒谬的(如果他们添加了调用parens来获取gen.__next__(),那么与01的比较会返回True我想但是,如果没有打电话,它可以保证False)。

至于reducethe docs中的reduce。 reducer函数的每次调用都使用先前调用的结果(存储在initializer函数的本地内部,除非它被传递给reducer函数时不可见)作为第一个参数(在第一次调用时,这是可选的第三个参数gen,或者第一个调用是使用b中的前两个元素执行的,而下一个结果来自输入可迭代的__next__ }。

因此,如果gen实际上已被调用(使用2中的前两个值),则第一个调用会将a用作3b作为5;下次调用的结果(a)为b4为gen(9)的下一个值,生成a = 2, b = 3 -> 5等。它出了头几个步骤。你会看到:

  1. a = 5, b = 4 -> 9
  2. a = 9, b = 5 -> 14
  3. a = 14, b = 6 -> 20
  4. reduce
  5. 等等;实际上,它只是使用sum作为lambda函数的缓慢/丑陋形式。

    关于你的第四个问题:发电机是懒惰的。当请求下一个值时,执行切换到生成器,并且当它生成时,生成器被“休眠”"直到请求下一个值。所以在这种情况下,是的,传递给reduce的{​​{1}}的每次调用都对应于gen的额外读取(第一次调用的两次读取,因为它需要获取累加器值开始),但它完全按需;这里没有真正的并行性;当gen恢复时,要求其输入值的代码暂停,等待结果;当没有请求它的值时,gen被"冻结"无限期(根本不是后台处理)。