为什么将 reduce 与非关联运算符一起使用被认为是不好的风格?

Why is using reduce with non-associative operators considered bad style?

正如 Guido 在他的 The fate of reduce() in Python 3000 post 中所说:

So now reduce(). This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly.

我对以下说法感到困惑:

the applicability of reduce() is pretty much limited to associative operators

python 中的 reduce 不只是一个 lfold 操作(从左到右)吗?我知道如果与集合或字典键一起使用,顺序可能是不确定的——这是唯一的原因吗?

下面是一个很好地使用 reduce 进行非关联操作的例子:

def pass_thru(prev, next_func):
    return next_func(prev)

def flow(seed, *funcs):
    return reduce(pass_thru, funcs, seed)

flow('HELLO',
     str.lower,
     str.capitalize,
     str.swapcase)
#returns 'hELLO'

我担心的是,我是否应该担心与 lfold、未来的多线程实现的非保证一致性,或者只是注意像集合和字典这样的非确定性迭代。

虽然我不得不说我同意你的观点,而且我真的很喜欢你提供的 flow 示例,

我可以看出 Guido 声称 reduce 不像直接循环那样明确的说法的一些优点。如果您不习惯 FP 的高阶函数,可能会感到困惑。

我认为map , filterzip 等高阶函数非常有用,它们本质上是声明性的,没有定义显式实现。

您可以使用 sparkmapmultiprocessing.Poolmap 或内置的 map,以及 return 值应该相同。

然而,当涉及到 reduce 时,实现本质上是串行的。事实上,您不会通过使用直接循环获得任何抽象。

由此可见reduce与Python之禅的冲突:

There should be one-- and preferably only one --obvious way to do it.