在Python中求非整数的和
在Python中,能不能对非整数的数字进行求和呢?
我试过这个命令
sum([[1], [2]])
想要得到 [1, 2]
,但是却出现了错误
Traceback (most recent call last):
File "<pyshell#28>", line 1, in <module>
sum([[1], [2]])
TypeError: unsupported operand type(s) for +: 'int' and 'list'
我猜测是因为求和的时候,它试图把0加到列表 [1]
上,导致失败。我知道有很多方法可以绕过这个限制(比如把东西放进一个类里,然后手动实现 __radd__
),但有没有更简单优雅的方法呢?
7 个回答
6
使用 itertools.chain
来连接列表会更高效。
>>> m = [[i] for i in range(200)]
>>> m
[[0], [1], [2], [3], [4], [5], [6], [7], [8], ...]
>>> from itertools import *
>>> list(chain(*m))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ...]
我个人更喜欢这种方法,而不是用列表推导式,因为很难记住哪个循环先执行。其实还有一个更高效的变体,list(chain.from_iterable(m))
。
微基准测试的结果(使用 Python 3 和 timeit
模块。列表大小为 p x q 意味着 m = [list(range(q)) for _ in range(p)]
):
list size | chain(*m) | sum(m,[]) | list comp | flatten |
----------+------------+---------------+------------+------------+
2 x 1 | 1.78 µs | 0.646 µs | 0.905 µs | 1.49 µs |
20 x 1 | 4.37 µs | 7.49 µs | 5.19 µs | 3.59 µs |
200 x 1 | 26.9 µs | 134 µs | 40 µs | 24.4 µs |
2000 x 1 | 233 µs | 12.2 ms | 360 µs | 203 µs |
----------+------------+---------------+------------+------------+
2 x 1 | 1.78 µs | 0.646 µs | 0.905 µs | 1.49 µs |
2 x 10 | 2.55 µs | 0.899 µs | 3.14 µs | 2.2 µs |
2 x 100 | 9.07 µs | 2.03 µs | 17.2 µs | 8.55 µs |
2 x 1000 | 51.3 µs | 21.9 µs | 139 µs | 49.5 µs |
----------+------------+---------------+------------+------------+
chain(*m) -> list(chain(*m))
sum(m,[]) -> sum(m, [])
list comp -> [j for i in m for j in i]
flatten -> icfi = chain.from_iterable; list(icfi(m))
结果显示,sum
只有在外层列表很短的时候才高效。但这时你还有一个更高效的选择:m[0]+m[1]
。
9
在除了数字以外的东西上使用 sum()
是个坏主意,因为这样做的效率很低,特别是对于序列、字符串等。
更好的做法是使用列表推导式来对你的列表进行求和。
[j for i in [[1],[2]] for j in i]
11
看起来你想要的是这个:
>>> sum([[1],[2]], [])
[1, 2]
你说得对,它试图把0加到[1]上,结果出错了。解决办法是给sum
多一个参数,指定开始的值,对于你来说,这个值应该是一个空列表。
补充一下:正如gnibbler所说,sum
并不是连接东西的好方法。如果你只是想把一系列东西聚合在一起,最好用reduce
,而不是自己写一个__radd__
函数来使用sum
。这里有个例子(和sum
一样有问题):
>>> reduce(lambda x, y: x+y, [[1],[2]])
[1, 2]