在Python中求非整数的和

4 投票
7 回答
2549 浏览
提问于 2025-04-16 01:43

在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]

撰写回答