任何()懒惰地评估?

时间:2016-09-06 12:01:55

标签: python

我正在编写一个脚本,我必须根据许多条件测试数字。如果满足任何条件,我想返回True,我希望以最快的方式做到这一点。

我的第一个想法是使用any()代替嵌套if语句或多个or链接我的条件。因为如果任何条件是True我会感到满意,我可以真正受益于any()懒惰并尽快返回True。

基于以下事实:以下打印是立即发生的,而不是在10(= 0 + 1 + 2 + 3 + 4)秒之后,我认为是。是这样的,还是我错了?

import time

def some(sec):
    time.sleep(sec)
    return True

print(any(some(x) for x in range(5)))

7 个答案:

答案 0 :(得分:15)

是,any()all()短路,一旦结果明确就中止:请参阅docs

  

所有(迭代)

     

如果iterable的所有元素都为真(或者如果是),则返回True   iterable是空的)。相当于:

def all(iterable):
    for element in iterable:
        if not element:
            return False
    return True
     

<强>任何(迭代)

     

如果iterable的任何元素为true,则返回True。如果是可迭代的   空,返回False。相当于:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

答案 1 :(得分:6)

all()any()函数在第一个&#34; true&#34;上发生短路。可迭代的元素,可迭代本身可以以非惰性方式构造。考虑这个例子:

>> any(x == 100 for x in range(10**8))
True

这需要几秒钟才能在Python 2中执行,因为range(10**8)构造了一个包含10 ** 8个元素的列表。同样的表达式在Python 3中立即运行,其中range()是懒惰的。

答案 2 :(得分:4)

正如Tim正确提到的那样,anyall会发生短路,但在您的代码中, lazy 的原因是使用了generators。例如,以下代码不会是惰性的:

print(any([slow_operation(x) for x in big_list]))

列表将完全构建和计算,然后作为参数传递给any

另一方面,

生成器是可按需计算每个项目的迭代器。它们可以是expressionsfunctions,有时也可以手动实现为惰性iterators

答案 3 :(得分:2)

是的,如下所示,它很懒惰:

JavaPairRDD<String, Iterable<String>> pairRDD = ...;
JavaPairRDD<String, Map<String, Integer>> resultPairRDD = pairRDD.mapValues(new Function<Iterable<String>, Map<String, Integer>>() {

    @Override
    public Map<String, Integer> call(Iterable<String> arg0) throws Exception {
        Map<String, Integer> countMap = new HashMap<String, Integer>();
        for(String s:arg0){
            int curCnt = countMap.containsKey(s) ? countMap.get(s) : 0;
            countMap.put(s, (curCnt+1));
        }
        return countMap;
    }
});

在测试第一项后第一次运行def some(x, result=True): print(x) return result >>> print(any(some(x) for x in range(5))) 0 True >>> print(any(some(x, False) for x in range(5))) 0 1 2 3 4 False 停止,即它使评估短路。

在第二轮中any()继续测试,直到序列耗尽。

答案 4 :(得分:2)

是的,这是一个实验,它比你的计时实验更明确地显示它:

import random

def some(x):
    print(x, end = ', ')
    return random.random() < 0.25

for i in range(5):
    print(any(some(x) for x in range(10)))

典型的运行:

0, 1, 2, True
0, 1, True
0, True
0, 1, 2, 3, True
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, False

答案 5 :(得分:0)

不。 All和Any支持短路,但它们不会使条件解释变得懒惰。

如果您希望使用惰性评估来计算All或Any,则需要向他们传递一个生成器。否则,值会在构建列表/集合/迭代器/任何内容的那一刻被评估

答案 6 :(得分:0)

JoshiRaez 是真正的正确答案。

这是一个例子

a = []

any([True, a[0]])

会失败

另一方面,使用 OR(或 AND)不会失败,因为它不是函数:

a = []
True or a[0]