如何在 reduce 函数中使用 python 生成器?
How to use python generators in reduce function?
有人可以帮我理解这段代码的执行吗?
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 是什么意思? gen不是生成器对象吗?
- 此外,reduce 函数如何记住分配给 a 和 b 的内容?
- 调用gen = foo()后,执行是否只是在函数和reduce语句之间切换?
如果有人能把生成器和reduce函数的功能映射出来,那将有很大帮助!谢谢!
如您所见,gen
是一个生成器; print
中的所有测试都是荒谬的(如果他们添加调用括号以获得 gen.__next__()
那么与 0
和 1
的比较将 return True
我想,但通过不调用它,可以保证 False
).
至于reduce
,那是在the docs。 reducer 函数的每次调用都使用先前调用的结果(内部存储在 reduce
函数的局部变量中,除非传递给 reducer 函数,否则不可见)作为第一个参数(在第一次调用时,这是可选的第三个参数 initializer
,或者第一次调用是使用 gen
中的前两个元素执行的),下一个输入迭代结果为 b
.
因此,如果实际上调用了 __next__
(使用 gen
的前两个值),则第一次调用将使用 2
作为 a
和 3
作为 b
;下一次调用的结果 (5
) 将是 a
,b
来自 gen (4
) 的下一个值,生成 9
,等等。步进它出前几步。你会看到:
a = 2, b = 3 -> 5
a = 5, b = 4 -> 9
a = 9, b = 5 -> 14
a = 14, b = 6 -> 20
等等;实际上,它只是使用 reduce
作为 sum
函数的 slow/ugly 形式。
关于你的第四个问题:生成器是懒惰的。当请求下一个值时,执行切换到生成器,当生成它时,生成器是 "hibernated" 直到请求下一个值。所以在这种情况下,是的,传递给 reduce
的 lambda
的每次调用都对应于 gen
的额外读取(第一次调用需要两次读取,因为它需要获得一个累加器值开始),但它完全是按需的;这里没有真正的并行性;当 gen
恢复时,要求它提供值的代码将暂停等待结果;当没有从中请求任何值时,gen
是 "frozen" 无限期(根本不是后台处理)。
有人可以帮我理解这段代码的执行吗?
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 是什么意思? gen不是生成器对象吗?
- 此外,reduce 函数如何记住分配给 a 和 b 的内容?
- 调用gen = foo()后,执行是否只是在函数和reduce语句之间切换?
如果有人能把生成器和reduce函数的功能映射出来,那将有很大帮助!谢谢!
如您所见,gen
是一个生成器; print
中的所有测试都是荒谬的(如果他们添加调用括号以获得 gen.__next__()
那么与 0
和 1
的比较将 return True
我想,但通过不调用它,可以保证 False
).
至于reduce
,那是在the docs。 reducer 函数的每次调用都使用先前调用的结果(内部存储在 reduce
函数的局部变量中,除非传递给 reducer 函数,否则不可见)作为第一个参数(在第一次调用时,这是可选的第三个参数 initializer
,或者第一次调用是使用 gen
中的前两个元素执行的),下一个输入迭代结果为 b
.
因此,如果实际上调用了 __next__
(使用 gen
的前两个值),则第一次调用将使用 2
作为 a
和 3
作为 b
;下一次调用的结果 (5
) 将是 a
,b
来自 gen (4
) 的下一个值,生成 9
,等等。步进它出前几步。你会看到:
a = 2, b = 3 -> 5
a = 5, b = 4 -> 9
a = 9, b = 5 -> 14
a = 14, b = 6 -> 20
等等;实际上,它只是使用 reduce
作为 sum
函数的 slow/ugly 形式。
关于你的第四个问题:生成器是懒惰的。当请求下一个值时,执行切换到生成器,当生成它时,生成器是 "hibernated" 直到请求下一个值。所以在这种情况下,是的,传递给 reduce
的 lambda
的每次调用都对应于 gen
的额外读取(第一次调用需要两次读取,因为它需要获得一个累加器值开始),但它完全是按需的;这里没有真正的并行性;当 gen
恢复时,要求它提供值的代码将暂停等待结果;当没有从中请求任何值时,gen
是 "frozen" 无限期(根本不是后台处理)。