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

reduce(x+;y,xs)和sum(xs)在python中不等价吗?,python,sum,tuples,reduce,equational-reasoning,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在这里失败?实际问题是,sum的默认起始值。引用 将iterable的起始项和项从左到右求和,并返回总数开始默认为0。iterable的项通常是数字,并且起始值不允许是字符串 但是,在reduce的情况下,如果没

然而,从函数等式的角度来看,我认为这两个词的意思是相同的:

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
的默认起始值。引用

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

但是,在
reduce
的情况下,如果没有给出可选的起始值,它将使用iterable中的第一个值作为初始值设定项。所以,
reduce
实际上是这样计算的

( ( (1, 'a') + (2, 'b') ) + (3, 'c') )
>>> sum(zip(x, y), tuple())
(1, 'a', 2, 'b', 3, 'c')
() + (1, 'a') + (2, 'b') + (3, 'c')
>>> tuple(item for items in zip(x, y) for item in items)
(1, 'a', 2, 'b', 3, 'c')
由于
sum
假定起始值为0,因此它的计算方式如下:

0 + (1, 'a') + (2, 'b') + (3, 'c')
在本例中,它尝试使用一个元组添加
0
,这就是您得到

TypeError:不支持+:'int'和'tuple'的操作数类型
要解决此问题,请将一个空元组传递给
sum
,如下所示

( ( (1, 'a') + (2, 'b') ) + (3, 'c') )
>>> sum(zip(x, y), tuple())
(1, 'a', 2, 'b', 3, 'c')
() + (1, 'a') + (2, 'b') + (3, 'c')
>>> tuple(item for items in zip(x, y) for item in items)
(1, 'a', 2, 'b', 3, 'c')
现在,初始值是一个空元组,计算过程如下

( ( (1, 'a') + (2, 'b') ) + (3, 'c') )
>>> sum(zip(x, y), tuple())
(1, 'a', 2, 'b', 3, 'c')
() + (1, 'a') + (2, 'b') + (3, 'c')
>>> tuple(item for items in zip(x, y) for item in items)
(1, 'a', 2, 'b', 3, 'c')
注意:在这两种情况下,将创建多个中间元组。为了避免这种情况,我建议将数据展平,并将其作为生成器表达式传递给
tuple
构造函数,如下所示

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

这让人觉得
sum
实际上是设计错误的:
start
应该默认为第一项,而不是
0
@thefourtheye啊,非常好的捕获,关于初始值;我不知道您可以传递自定义的起始值。对于
sum(zip(x,y),tuple())
我仍然得到“TypeError:无法使用灵活类型执行reduce”。你知道为什么吗?@georg那么
sum([])
会是什么?@HenryHenrinson
TypeError
with
reduce
sum
?@HenryHenrinson你使用的是哪个版本的Python?我试过Py 2.7和3.4,两个都很好