reduce() 有啥问题?
Posted
技术标签:
【中文标题】reduce() 有啥问题?【英文标题】:What is the problem with reduce()?reduce() 有什么问题? 【发布时间】:2010-09-15 22:37:57 【问题描述】:网上似乎有很多关于 python 3.0 中 reduce() 函数的更改以及如何删除它的讨论。我很难理解为什么会这样;我发现在各种情况下使用它是很合理的。如果轻视只是主观的,我无法想象这么多人会关心它。
我错过了什么? reduce() 有什么问题?
【问题讨论】:
【参考方案1】:正如 Guido 在他的 The fate of reduce() in Python 3000 帖子中所说:
所以现在减少()。这实际上是我一直最讨厌的一个,因为除了一些涉及 + 或 * 的示例之外,几乎每次我看到带有非平凡函数参数的 reduce() 调用时,我都需要拿起笔和纸来在我理解 reduce() 应该做什么之前,先画出实际输入该函数的内容。所以在我看来,reduce() 的适用性几乎仅限于关联运算符,在所有其他情况下,最好明确地写出累积循环。
Functional Programming HOWTO 文章中有一个令人困惑的reduce
的绝佳示例:
快,下面的代码在做什么?
total = reduce(lambda a, b: (0, a[1] + b[1]), items)[1]
你可以弄明白,但是需要时间去解开表达式来弄明白 这是怎么回事。使用简短的嵌套 def 语句会使事情变得更好:
def combine (a, b): return 0, a[1] + b[1] total = reduce(combine, items)[1]
但如果我只使用一个 for 循环就更好了:
total = 0 for a, b in items: total += b
或者 sum() 内置和一个生成器表达式:
total = sum(b for a,b in items)
reduce() 的许多用法在写成 for 循环时更加清晰。
【讨论】:
在这种情况下可能会更简单:sum (b for a, b in items) reduce 代码不等同于 for 循环。这是等效的:total = reduce(lambda total, (a,b): total + b, items, 0)
"reduce 函数可以混淆代码的意图。因此,应该从语言中删除 reduce。"诚然,我不知道有人这么说,但它是不合逻辑的。
观点成立,但公平地说,在你的例子中加入一个 lambda 相当于把一件沾满血迹的衬衫交给警察阵容中的一个人。我不会争辩说 reduce() 一开始并不令人困惑,但 functools 中的一切都是你开始的时候。随着我学会使用 functools,我发现它们越来越有用。现在,如果你想要一些令人困惑的例子,请查看 itertools()。我也在学习爱他们,但第一次约会很艰难。 :-)
参数是“让我们移动reduce
,因为它可以用来写不清楚的代码。”。好吧,**
、+
和 -
也可以。我们应该将它们移至functools
吗?【参考方案2】:
reduce()
没有被删除——它只是被移动到functools
模块中。 Guido 的推理是,除了求和之类的琐碎情况外,使用reduce()
编写的代码通常在编写为累加循环时会更清晰。
【讨论】:
呸,这是可怕的推理:( 是吗? Python 的大部分哲学都是关于编写清晰明了的代码。对 reduce() 的典型调用通常需要我拿出铅笔并绘制出调用函数的图形。 除非你能向我展示一个显着的性能提升(至少 2 倍),否则我将在任何一天都将“清晰和明显”而不是“表达的紧凑性”。跨度> 【参考方案3】:人们担心它会鼓励一种混淆的编程风格,做一些可以通过更清晰的方法来实现的事情。
我并不反对减少自己,我有时也觉得它是一个有用的工具。
【讨论】:
【参考方案4】:reduce 存在的主要原因是避免使用累加器编写显式 for 循环。尽管 python 有一些支持函数式风格的工具,但不鼓励这样做。如果你喜欢“真实的”而不是“pythonic”的函数式风格 - 请改用现代的 Lisp(Clojure?)或 Haskell。
【讨论】:
这就像告诉华裔美国人如果他们不喜欢他们在美国受到的待遇就滚回中国。我们都在这里使广泛使用的语言变得更好。无需要求人们使用不同的语言。大多数时候他们不能因为诸如包的可用性等限制。 @episodeyang 这是一个奇怪的比喻,带有很多情感包袱,需要带入技术讨论。函数范式并没有使 Python “更好”(或更糟),它只是 not a functional language by the statement of its own creator。直言不讳并建议人们停止将 Lisp/Clojure/Haskell 习语硬塞进像 Python 这样的多范式、基本命令式、非函数式语言中,这并没有错。【参考方案5】:Horner 方法使用 reduce 计算多项式的值既紧凑又富有表现力。
计算 x 处的多项式值。 a 是多项式的系数数组
def poynomialValue(a,x):
return reduce(lambda value, coef: value*x + coef, a)
【讨论】:
这并不是真的试图回答 OP 的问题。 “为什么reduce
有问题?”答案:“这是reduce
的用例”。
这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review
一个强大的语言工具总是可以用来简洁但不够清晰。我想举一个例子,reduce 可以用来紧凑地表达一个算法。请注意,这是一个非关联运算符的示例。
没有人争辩 reduce
不能永远被清楚地使用,甚至没有很多例子可以很好地适合它。问题是它有什么问题,而不是它有什么问题。反对 reduce 的理由是它容易被误用,损害可读性并且不符合non-functional orientation of Python。这些是对 OP 关于为什么将其降级为 functools
的问题的可能答案。以上是关于reduce() 有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章