这个函数必须使用reduce()吗,还是有更符合Python风格的方法?
如果我有一个数值,还有一系列我想要和这个数值相乘的其他数:
n = 10
terms = [1,2,3,4]
有没有办法用列表推导式来做到类似这样的事情:
n *= (term for term in terms) #not working...
还是说唯一的方法是:
n *= reduce(lambda x,y: x*y, terms)
这是在Python 2.6.2上进行的。谢谢!
3 个回答
还有一种方法:
import operator
n = reduce(operator.mul, terms, n)
在我看来,reduce
是处理这个问题的最佳方法,但你不一定非得用 lambda 表达式;你也可以直接使用 *
运算符:
import operator
n *= reduce(operator.mul, terms)
现在 n
的值是 240。想了解更多信息,可以查看 运算符模块 的文档。
使用`reduce`并不是唯一的方法。你也可以用一个简单的循环来实现:
for term in terms:
n *= term
我觉得这样写比用`reduce`要清楚多了,特别是考虑到很多Python程序员根本没见过`reduce`,而且这个名字对第一次看到它的人来说并不能很好地说明它的作用。
“Pythonic”并不意味着要把所有东西都写成列表推导式或者总是尽量使用函数式风格。Python是一种支持多种编程风格的语言,在合适的时候写简单的命令式代码也是Pythonic。
Guido van Rossum(Python的创始人)也不想在Python中使用`reduce`:
所以现在有了`reduce()`。其实这是我一直最讨厌的一个,因为除了少数涉及`+`或`*`的例子,几乎每次我看到一个带有复杂函数参数的`reduce()`调用,我都需要拿出纸和笔来画图,弄清楚到底传给那个函数的是什么,才能理解`reduce()`到底是干什么的。在我看来,`reduce()`的适用性基本上只限于结合运算符,而在其他情况下,明确写出累加循环会更好。
结合运算符并不多。(结合运算符是指那些满足(a X b) X c等于a X (b X c)的运算符。)我觉得它们基本上只限于`+`、`*`、`&`、`|`、`^`和短路运算符`and`/`or`。我们已经有了`sum()`;我很乐意用`product()`来替代`reduce()`,这样就解决了两个最常用的情况。[...]
在Python 3中,`reduce`被移到了`functools`模块里。