为什么sum()没有关键arg?

时间:2015-07-22 21:45:15

标签: python built-in

今天,我自动写了一些这样的事情:

class Foo():
    def __init__(self, x):
        self.x = x

s = [Foo(1), Foo(2), Foo(3)]
sum_x = sum(s, key = lambda foo: foo.x)

得到了这个:

  

TypeError:sum()不带关键字参数

sum()没有key arg有什么特殊原因吗?

3 个答案:

答案 0 :(得分:6)

因为您可以改为编写@Document。如果您尝试使用其中一个确实采用sum(foo.x for foo in s)参数(keysortedmin等等的函数执行此操作,则该函数最终会返回键(而不是原始项),并且按键排序时获取原始项是非常棘手的,以至于Python通过关键字参数为您提供了内置方法。

因此:max没有特殊理由不接受sum;相反,那些其他功能有特殊的原因,为什么他们采取keykey是例外,而不是规则。

答案 1 :(得分:2)

没有key参数,因为sum()未返回原始元素(例如sorted()min()max())。相反,它只是对输入进行求和。

如果min()没有采用key参数,则无法根据属性返回最小Foo()个对象;它只能返回该属性的值。但是sum()不起作用,它不需要保留原始对象。

您可以轻松转换生成器表达式中的输入:

sum(item.x for item in s)

答案 2 :(得分:1)

虽然没有key参数,但好消息是可以使用sum 与您的Foo对象!其他人已经指出了最简单的方法 这样做

sum(item.x for item in s)

但是,也可以在不理解的情况下使用它。

对象添加

为了使总和发挥作用,基本的补充需要先行。

In [2]: class Foo:
...:     def __init__(self, x):
...:         self.x = x
...:

In [3]: Foo(3) + Foo(5)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-f0e9c3a4abb9> in <module>()
----> 1 Foo(3) + Foo(5)

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

我们可以通过定义__add__方法来启用添加。

In [4]: class Foo:
...:     def __init__(self, x):
...:         self.x = x
...:     def __add__(self, other):
...:         return Foo(self.x + other.x)
...:

In [5]: Foo(3) + Foo(5)
Out[5]: <__main__.Foo at 0x102bdc2e8>

明确说明它有效

In [6]: result = Foo(3) + Foo(5)

In [7]: result.x
Out[7]: 8

但这并不能解决所有问题。

In [8]: sum([Foo(3), Foo(5)])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-70968119f3ba> in <module>()
----> 1 sum([Foo(3), Foo(5)])

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

我们没有尝试添加int,但sum函数认为我们做了。是什么给了什么?

sum功能

使用ipython检查sum函数,你可以看到它包含一个 可选的start参数

In [1]: sum??
Docstring:
sum(iterable[, start]) -> value

Return the sum of an iterable of numbers (NOT strings) plus the value
of parameter 'start' (which defaults to 0).  When the iterable is
empty, return start.
Type:      builtin_function_or_method

因此,sum(s)sum(s, 0)相同,就是这个开始 导致错误的值。我们所要做的就是替换起始值 使用等效的Foo对象

In [9]: sum([Foo(3), Foo(5)], Foo(0))
Out[9]: <__main__.Foo at 0x102bdc9e8>

In [10]: result = sum([Foo(3), Foo(5)], Foo(0))

In [11]: result.x
Out[11]: 8

这也适用于其他一些类型

In [12]: sum([[1,2,3], [4,5,6]], [])
Out[12]: [1, 2, 3, 4, 5, 6]

但不是全部

In [13]: sum(["abc", "def"], "")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-452a33de0457> in <module>()
----> 1 sum(["abc", "def"], "")

TypeError: sum() can't sum strings [use ''.join(seq) instead]
相关问题