在Python中,reduce(x + y,xs)和sum(xs)不相等?

时间:2015-02-20 09:08:58

标签: python sum tuples reduce 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

为什么sum在这里失败?

1 个答案:

答案 0 :(得分:4)

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

  

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

但是,在reduce的情况下,如果没有给出可选的起始值,它将使用iterable中的第一个值作为初始值。所以,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')