Python 的 reduce() 会短路吗?

14 投票
6 回答
2594 浏览
提问于 2025-04-16 03:18

如果我这样做:

result = reduce(operator.and_, [False] * 1000)

它会在第一个结果后就停止吗?(因为 False & anything == False

类似的:

result = reduce(operator.or_, [True] * 1000)

6 个回答

3

可能有一种替代的 reduce 实现方式会表现得很好(可以参考 reduce 的命运)。

这个想法在我的设计中非常有效,让事情变得更加清晰。

def ipairs(seq):
    prev = None
    for item in seq:
        if prev is not None:
            yield (prev, item)
        prev = item

def iapply(seq, func):
    for a, b in ipairs(seq):
        yield func(a, b)

def satisfy(seq, cond):
    return all(iapply(seq, cond))

def is_uniform(seq):
    return satisfy(seq, lambda a, b: a == b)

正如你所看到的,reduce 被拆分成了 iapplyipairs

请注意,这并不等同于

def ireduce(seq, func):
    prev = None
    for item in seq:
        if prev is None:
            prev = item
        else:
            prev = func(prev, item)
    return prev
5

reduce()这个函数不仅不会短路,而且在处理所有的项目时也不可能短路,因为它每次只考虑两个项目。再者,它根本不知道用来处理这些项目的函数在什么情况下会短路。(如果函数能有一个属性,告诉reduce()它在什么值时开始短路,那就太好了,但实际上并没有这样的属性。)

23

它并没有。你可以用的替代方法是 anyall

result = reduce(operator.and_, [False] * 1000)
result = reduce(operator.or_, [True] * 1000)

可以被替换为

result = all([False] * 1000)
result = any([True] * 1000)

它们可以短路。

时间结果显示了它们之间的区别:

In [1]: import operator

In [2]: timeit result = reduce(operator.and_, [False] * 1000)
10000 loops, best of 3: 113 us per loop

In [3]: timeit result = all([False] * 1000)
100000 loops, best of 3: 5.59 us per loop

In [4]: timeit result = reduce(operator.or_, [True] * 1000)
10000 loops, best of 3: 113 us per loop

In [5]: timeit result = any([True] * 1000)
100000 loops, best of 3: 5.49 us per loop

撰写回答