Python 一行求和实现?

2 投票
3 回答
4877 浏览
提问于 2025-04-19 20:52

首先,我问这个问题纯粹是出于好奇,想看看大家的单行代码技巧。sum()这个函数仍然是计算列表中对象总和的最佳选择。

不过正如我所说,我只是出于好奇:有没有办法在一行代码里,不用sum()函数来计算一个list中的对象总和呢?假设这个列表是range(0, 100)

我完全不知道该怎么做,但因为Python真的很棒而且灵活,所以我相信这是可能的。

3 个回答

1

Python 可能不是处理递归问题的最佳语言,原因有几个:首先,它不支持尾递归;其次,函数调用的开销很大;再者,递归的深度有限制,不能进行太深的递归;最后,切片操作的复杂度是 O(n)(这里的 n 是切片中元素的数量)。

不过,你可以用它来写一行代码!

一种方法是不断地取出第一个元素并加到结果中,直到序列用完为止:

>>> sum_func = lambda x: x[0] + sum_func(x[1:]) if x else 0
>>> sum_func(range(100))
4950

这个过程会一直进行,只要 if x 成立(也就是说 x 不是空的)。这种方法暴露了在 Python 中使用递归的所有缺点:对于长度大约为 300 的序列,它会达到递归限制,复杂度是 O(n**2),而且相比于内置的 sumreduce 方法,它的速度非常慢。

我们可以通过使用分治法来减轻其中一个缺点:

>>> sum_func = lambda x: sum_func(x[:len(x)//2]) + sum_func(x[len(x)//2:]) if len(x) > 1 else x[0]
>>> sum_func(range(100))
4950

这次它会对列表的两个部分进行递归,从而将递归的深度从 n 降低到 log2(n),这样可以处理更长的序列。不过,它的速度并没有比上面的方法快。


当然,还有一种作弊的方法:

>>> from numpy import sum
>>> sum(range(100))
4950

如果你真的想要快速解决这个问题 :-)

5

你可以用一种函数式的方法,使用 reduce 函数和一个加法函数(比如一个 lambda 表达式operator.add):

>>> from operator import add
>>> reduce(add, range(0, 100))
4950

(注意,在 Python 3.x 中,你需要先执行 from functools import reduce。)

根据文档,reduce(function, iterable) 的作用是:

function 这个需要两个参数的函数,逐个应用到 iterable 中的每个元素上,从左到右进行处理,最终把 iterable 简化成一个单一的值。

1

为了好玩,这里有一个解决方案,完全不需要任何内置函数。它基本上是对 reduce 函数的重新实现,使用了一点点神奇的 lambda 表达式。

>>>>(lambda f: lambda *args: f(f, *args))(lambda self, f, seq, d: d if not seq else f(seq[0], self(self, f, seq[1:], d)))(lambda a,b: a+b, range(100), 0)
4950

撰写回答