为什么 sum() 没有关键参数?
Why sum() does not have the key arg?
今天,我自动写了一些这样的东西:
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() takes no keyword arguments
sum()
没有 key
arg 有什么特殊原因吗?
因为您可以只写 sum(foo.x for foo in s)
。如果您尝试使用带有 key
参数(sorted
、min
、max
等)的函数之一执行此操作,该函数最终会返回键而不是原始项目,并且在按键排序时获取原始项目非常棘手,以至于 Python 为您提供了一种通过关键字参数执行此操作的内置方法。
因此:sum
没有特殊原因不参加 key
;相反,那些其他函数有特殊原因 do 需要 key
。 key
是例外,不是规则。
没有 key
参数,因为 sum()
没有 return 原始元素(如 sorted()
、min()
和 max()
做)。相反,它只是对输入求和。
如果,比方说,min()
没有采用 key
参数,它就不能 return 基于属性的最小 Foo()
对象;它只能 return 该属性的值。但是 sum()
不是这样的,它不需要保留原始对象。
您可以轻松地转换生成器表达式中的输入:
sum(item.x for item in s)
虽然没有 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]
今天,我自动写了一些这样的东西:
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() takes no keyword arguments
sum()
没有 key
arg 有什么特殊原因吗?
因为您可以只写 sum(foo.x for foo in s)
。如果您尝试使用带有 key
参数(sorted
、min
、max
等)的函数之一执行此操作,该函数最终会返回键而不是原始项目,并且在按键排序时获取原始项目非常棘手,以至于 Python 为您提供了一种通过关键字参数执行此操作的内置方法。
因此:sum
没有特殊原因不参加 key
;相反,那些其他函数有特殊原因 do 需要 key
。 key
是例外,不是规则。
没有 key
参数,因为 sum()
没有 return 原始元素(如 sorted()
、min()
和 max()
做)。相反,它只是对输入求和。
如果,比方说,min()
没有采用 key
参数,它就不能 return 基于属性的最小 Foo()
对象;它只能 return 该属性的值。但是 sum()
不是这样的,它不需要保留原始对象。
您可以轻松地转换生成器表达式中的输入:
sum(item.x for item in s)
虽然没有 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]