繁体   English   中英

在Python中,reduce和any / all的预期性能差异?

[英]In Python, difference in expected performance of reduce and any/all?

我试图找出Python 2.7.3中的以下操作是否短路:

  • 用逻辑“或”或“与”减少
  • 任何/所有

因此,我定义了一个睡眠500ms的函数,打印传入的值并返回它。

def f(x):
    time.sleep(0.5)
    print 'x', x
    return x

然后,我使用any运行以下代码,该代码实际上在每个列表元素上调用f()并将返回值与0进行比较。这只会在列表的第一个元素0上发生。

In [1]: any([f(i)==0 for i in range(3)])
x 0
x 1
x 2

这表明任何一个都不会短路,因为它在所有列表元素上都调用f()。 它仅指示整个列表首先计算。 接下来,我用reduce进行了评估。

In [2]: reduce(lambda x,y: x or f(y)==0, range(3), False)
x 0

显然, 减少短路。 *很明显,一旦调用函数或发生短路,就不会计算出整个列表。*为了确保这一点,我还为以下代码计时

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

用于减少

In [4]: timeit any([True] * 10000)
10000 loops, best of 3: 43.8 us per loop

对于任何 由此得出的结论是, 任何一种方法都比减少速度要快 ,因为它可能会短路。 那是什么

===============

回答

为了获得性能,最好的方法似乎是从列表中计算出一个生成器,然后在其上使用任何生成器。

In [1]: any(f(i)==0 for i in range(3))
x 0
 any([f(i)==0 for i in range(3)]) 

这与:

l = [f(i)==0 for i in range(3)]  # [True, False, False]
any(l)

您正在生成整个列表,并在调用any元素之前为每个元素运行f 您将需要使用生成器来避免处理整个列表:

any(f(i)==0 for i in range(3))

现在这会按预期短路。

正如@Jon所指出的那样: 永不 reduce短路,这仅是您的回调才可以。 any的目的是在遇到的第一个True返回Truereduce的目的是迭代所有元素并在最后返回单个值; 而这正是他们所做的。 问题出在您的部分代码中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM