Accumulate 不适用于求和,但适用于等效的 lambda 函数。为什么?
Accumulate does not work with sum, but does work with equivalent lambda function. Why?
我在玩累加函数,我认为 accumulate(<int[]>,sum)
会产生一个累加和。但是,运行使用以下代码会导致错误。
from itertools import accumulate
print([*accumulate([1,2,3],sum)])
具体来说,我得到 TypeError: 'int' object is not iterable
。另一方面,运行使用 lambda 函数执行完全相同的操作会产生预期的结果。
from itertools import accumulate
print([*accumulate([1,2,3],lambda *args:sum(args))])
# [1, 3, 6]
当我运行这段代码使用一个命名的自定义函数做同样的事情时,我得到了另一个奇怪的结果。
from itertools import accumulate
def my_sum(*args): return sum(args)
print([*accumulate([1,2,3]),my_sum])
#[1, 3, 6, <function my_sum at 0x7fd57139caf0>]
尚不清楚是什么导致了行为上的差异。 sum,my_sum,
和匿名函数属于“函数”类型,因此类型本身并不能决定事情。我还做了以下事情,看看我是否能得到其他线索;我注意到的唯一区别是 sum
是内置函数。
print(lambda *args:sum(args),my_sum,sum,sep='\n')
# <function <lambda> at 0x7fd57139cb80>
# <function my_sum at 0x7fd57139cc10>
# <built-in function sum>
这是怎么回事?
来自docs:对于itertools.accumulate(iterable[, func, *, initial=None])
If func
is supplied, it should be a function of two arguments. Elements of the input iterable
may be any type that can be accepted as arguments to func
. (For example, with the default operation of addition, elements may be any addable type including Decimal
or Fraction
.)
sum()
确实接受两个参数,但第一个参数 必须 是一个可迭代的,第二个是起始值。 Docs
让我们通过打印 my_sum()
中的参数,看看 accumulate()
传递给它的 func
参数的内容
def my_sum(*args):
print(args)
return sum(args)
accumulate([1, 2, 3], my_sum)
# (1, 2)
# (3, 3)
因此accumulate()
将最后一个累加值和下一个数字传递给func
。由于 sum()
的第一个参数必须是可迭代的(int
不是),你会得到那个错误。
你的 lambda 不 等同于 sum()
:sum()
需要 一个可迭代的 和 returns 其元素的总和。您的 lambda 接受 任意数量的参数 和 returns 这些参数的总和。要对此进行测试,请查看执行 sum([1, 2, 3])
和 my_sum([1, 2, 3])
.
时得到的结果
在你的最后一个例子中你有一个错字。您没有将 my_sum
传递给 accumulate()
。您创建了一个列表,其中包含 accumulate([1, 2, 3])
的结果,然后是函数 my_sum
。将其修复为 print([*accumulate([1,2,3], my_sum)])
,您将获得与 lambda 情况相同的输出。
请注意,不提供 func
的行为就好像 func=operator.add
一样,并且会给您一个累计金额。
>>> accumulate([1, 2, 3])
[1, 3, 6]
我在玩累加函数,我认为 accumulate(<int[]>,sum)
会产生一个累加和。但是,运行使用以下代码会导致错误。
from itertools import accumulate
print([*accumulate([1,2,3],sum)])
具体来说,我得到 TypeError: 'int' object is not iterable
。另一方面,运行使用 lambda 函数执行完全相同的操作会产生预期的结果。
from itertools import accumulate
print([*accumulate([1,2,3],lambda *args:sum(args))])
# [1, 3, 6]
当我运行这段代码使用一个命名的自定义函数做同样的事情时,我得到了另一个奇怪的结果。
from itertools import accumulate
def my_sum(*args): return sum(args)
print([*accumulate([1,2,3]),my_sum])
#[1, 3, 6, <function my_sum at 0x7fd57139caf0>]
尚不清楚是什么导致了行为上的差异。 sum,my_sum,
和匿名函数属于“函数”类型,因此类型本身并不能决定事情。我还做了以下事情,看看我是否能得到其他线索;我注意到的唯一区别是 sum
是内置函数。
print(lambda *args:sum(args),my_sum,sum,sep='\n')
# <function <lambda> at 0x7fd57139cb80>
# <function my_sum at 0x7fd57139cc10>
# <built-in function sum>
这是怎么回事?
来自docs:对于itertools.accumulate(iterable[, func, *, initial=None])
If
func
is supplied, it should be a function of two arguments. Elements of the inputiterable
may be any type that can be accepted as arguments tofunc
. (For example, with the default operation of addition, elements may be any addable type includingDecimal
orFraction
.)
sum()
确实接受两个参数,但第一个参数 必须 是一个可迭代的,第二个是起始值。 Docs
让我们通过打印 my_sum()
accumulate()
传递给它的 func
参数的内容
def my_sum(*args):
print(args)
return sum(args)
accumulate([1, 2, 3], my_sum)
# (1, 2)
# (3, 3)
因此accumulate()
将最后一个累加值和下一个数字传递给func
。由于 sum()
的第一个参数必须是可迭代的(int
不是),你会得到那个错误。
你的 lambda 不 等同于 sum()
:sum()
需要 一个可迭代的 和 returns 其元素的总和。您的 lambda 接受 任意数量的参数 和 returns 这些参数的总和。要对此进行测试,请查看执行 sum([1, 2, 3])
和 my_sum([1, 2, 3])
.
在你的最后一个例子中你有一个错字。您没有将 my_sum
传递给 accumulate()
。您创建了一个列表,其中包含 accumulate([1, 2, 3])
的结果,然后是函数 my_sum
。将其修复为 print([*accumulate([1,2,3], my_sum)])
,您将获得与 lambda 情况相同的输出。
请注意,不提供 func
的行为就好像 func=operator.add
一样,并且会给您一个累计金额。
>>> accumulate([1, 2, 3])
[1, 3, 6]