reduce(x + y,xs)和sum(xs)在python中不等效吗?

Hen*_*son 3 python reduce tuples sum equational-reasoning

从功能方程式的角度来看,我希望两者的含义相同:

x = [1, 2, 3]
y = ['a', 'b', 'c']

reduce(lambda x, y: x + y, zip(x, y))  # works

sum(zip(x, y))  # fails
Run Code Online (Sandbox Code Playgroud)

为什么sum在这里失败?

the*_*eye 5

实际的问题是使用sum的默认起始值​​。引用文档

求和从左到右开始,迭代的项返回总数。start默认为0。可迭代的项通常是数字,并且起始值不允许为字符串。

但是,在的情况下reduce,如果未提供可选的起始值,它将使用iterable中的第一个值作为初始化程序。因此,reduce实际上是这样评估

( ( (1, 'a') + (2, 'b') ) + (3, 'c') )
Run Code Online (Sandbox Code Playgroud)

由于sum假设起始值为0,因此它会像这样评估它,

0 + (1, 'a') + (2, 'b') + (3, 'c')
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它尝试添加0一个元组,这就是为什么

( ( (1, 'a') + (2, 'b') ) + (3, 'c') )
Run Code Online (Sandbox Code Playgroud)

要解决此问题,请将一个空的元组传递到sum的开头,如下所示

>>> sum(zip(x, y), tuple())
(1, 'a', 2, 'b', 3, 'c')
Run Code Online (Sandbox Code Playgroud)

现在,初始值是一个空元组,评估就这样进行

() + (1, 'a') + (2, 'b') + (3, 'c')
Run Code Online (Sandbox Code Playgroud)

注意:在这两种情况下,将创建多个中间元组。为了避免这种情况,我建议将数据展平,并将其tuple作为生成器表达式传递给构造函数,如下所示

>>> tuple(item for items in zip(x, y) for item in items)
(1, 'a', 2, 'b', 3, 'c')
Run Code Online (Sandbox Code Playgroud)