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

如何在reduce函数中使用python生成器?,python,generator,reduce,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函数如何

有人能帮我理解这段代码的执行吗

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语句之间切换

如果有人能介绍一下生成器和reduce函数的功能,那将非常有帮助!谢谢

正如您所注意到的,
gen
是一个生成器;
print
中的所有测试都是毫无意义的(如果他们添加了call parens来获取
gen.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
,那么与
0
1
的比较将返回
True
,但如果不调用它,就保证
为False

至于
reduce
,这是一个很好的例子。reducer函数的每次调用都使用前一次调用的结果(存储在
reduce
函数的局部变量中,除非传递给reducer函数,否则不可见)作为第一个参数(在第一次调用时,这可能是可选的第三个参数
初始值设定项
,或者第一次调用是使用
gen
中的前两个元素执行的),输入iterable的下一个结果是
b

因此,如果实际调用了
\uuuuuuuuuuuuuu
(使用
gen
中的前两个值),第一次调用将使用
2
作为
a
3
作为
b
;下一次调用的结果(
5
)将是
a
,而
b
是gen code>中的下一个值(
4
),生成
9
,等等。在开始的几个步骤中逐步执行。您将看到:

  • a=2,b=3->5
  • a=5,b=4->9
  • a=9,b=5->14
  • a=14,b=6->20
  • 以此类推;实际上,它只是使用
    reduce
    作为
    sum
    函数的一种缓慢/丑陋的形式


    至于你的第四个问题:生成器是惰性的。当请求下一个值时,执行切换到生成器,当生成该值时,生成器处于“休眠”状态因此,在这种情况下,是的,
    lambda
    传递到
    reduce
    的每次调用都对应于从
    gen
    读取的附加值(第一次调用读取两次,因为它需要获得累加器值才能启动),但它完全是按需执行的;这里没有真正的并行性;当
    gen
    恢复时,请求它提供值的代码将暂停,等待结果;当没有请求它提供值时,
    gen
    将无限期地“冻结”(根本不是后台处理)如果你用
    操作符替换
    lambda
    ,它至少会变得不那么难看。add
    @chepner:True,虽然简单的
    sum(gen)
    会更漂亮。:-)或者如果你必须使用
    reduce
    ,则将其与
    functools.partial一起使用。partial
    制作一个命名的专用减速机,例如
    mysum=functools.partial(reduce,operator.add)
    myproduct=functools.partial(reduce,operator.mul)
    ,等等,所以当您使用它时,它更具有自我记录功能(
    mysum(gen)
    myproduct(gen)
    更为明显)。谢谢你的精彩解释。我唯一想指出的是,当我刚刚调试它时,它从a=0,b=1开始,然后a=1,b=2,a=3,b=3,然后一直上升到a=45。@ce1:是的,就像我说的,如果
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu next\uuuuuuuuu
    用法添加了paren(因此它实际上被调用),您会看到它从2和3开始。但是如果没有调用参数,当
    reduce
    开始时,生成器没有运行,因此它将从0和1开始。