Python 的 reduce() 会短路吗?
如果我这样做:
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 被拆分成了 iapply 和 ipairs。
请注意,这并不等同于
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
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