简体   繁体   English

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

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

I was trying to find out if the below operations in Python 2.7.3 short circuit or not: 我试图找出Python 2.7.3中的以下操作是否短路:

  • reduce with a logical 'or' or an 'and' 用逻辑“或”或“与”减少
  • any/all 任何/所有

So I defined a function which sleeps for 500ms, prints the passed in value and returns it. 因此,我定义了一个睡眠500ms的函数,打印传入的值并返回它。

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

Then I ran the below code using any , which essentially calls f() on each list element and compares the return value to 0. This will happen only on the first element of the list, which is 0. 然后,我使用any运行以下代码,该代码实际上在每个列表元素上调用f()并将返回值与0进行比较。这只会在列表的第一个元素0上发生。

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

This indicates any does not short-circuit as it calls f() on all the list elements. 这表明任何一个都不会短路,因为它在所有列表元素上都调用f()。 It just indicates that the entire list is computed first. 它仅指示整个列表首先计算。 Next, I used reduce to evaluate the same. 接下来,我用reduce进行了评估。

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

Clearly, reduce short-circuits. 显然, 减少短路。 *Its only clear that the entire list is not computed once the call back function or short-circuits.* Just to make sure, I also timed the following code *很明显,一旦调用函数或发生短路,就不会计算出整个列表。*为了确保这一点,我还为以下代码计时

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

for reduce and 用于减少

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

for any . 对于任何 From this one will conclude that any is faster than reduce, because it probably short-circuits. 由此得出的结论是, 任何一种方法都比减少速度要快 ,因为它可能会短路。 So what is it? 那是什么

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

Answer 回答

Wrt performance, the best way forward seems might be to compute a generator from the list and then use any on it. 为了获得性能,最好的方法似乎是从列表中计算出一个生成器,然后在其上使用任何生成器。

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

This is the same as: 这与:

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

You're generating the entire list and are running f for every element, before any is invoked. 您正在生成整个列表,并在调用any元素之前为每个元素运行f You would need to use a generator instead to avoid having the entire list processed: 您将需要使用生成器来避免处理整个列表:

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

This now short-circuits as expected. 现在这会按预期短路。

And as noted by @Jon: reduce never short-circuits, it's only your callback that does. 正如@Jon所指出的那样: 永不 reduce短路,这仅是您的回调才可以。 The purpose of any is to return True at the first True that is encountered, the purpose of reduce is to iterate all elements and return a single value at the end; any的目的是在遇到的第一个True返回Truereduce的目的是迭代所有元素并在最后返回单个值; and that's exactly what they do. 而这正是他们所做的。 The problem is in your part of the code here. 问题出在您的部分代码中。

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

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