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

reduce(x+y, xs) and sum(xs) are not equivalent in python?

但是,从函数方程式的角度来看,我希望两者的意思相同:

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

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

sum(zip(x, y))  # fails

为什么 sum 在这里失败了?

实际问题是 sum 的默认起始值​​。引用 documentation,

Sums start and the items of an iterable from left to right and returns the total. start defaults to 0. The iterable‘s items are normally numbers, and the start value is not allowed to be a string.

但是,在 reduce 的情况下,如果没有给出可选的起始值,它将使用可迭代对象中的第一个值作为初始值设定项。所以,reduce其实是这样评价的

( ( (1, 'a') + (2, 'b') ) + (3, 'c') )

由于sum假设起始值为0,所以它是这样计算的,

0 + (1, 'a') + (2, 'b') + (3, 'c')

在这种情况下,它会尝试使用元组添加 0,这就是为什么您会得到

TypeError: unsupported operand type(s) for +: 'int' and 'tuple'

要解决这个问题,将一个空元组传递到 sum 的开头,就像这样

>>> sum(zip(x, y), tuple())
(1, 'a', 2, 'b', 3, 'c')

现在,初始值是一个空元组,评估是这样发生的

() + (1, 'a') + (2, 'b') + (3, 'c')

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

>>> tuple(item for items in zip(x, y) for item in items)
(1, 'a', 2, 'b', 3, 'c')