2016-09-06 150 views
5

我正在写一个脚本,在这个脚本中我必须针对许多条件测试数字。如果任何的条件都满足,我想返回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))) 
+4

是 - 这是偷懒...... –

+0

感谢!这同样适用于所有'()'我想象 –

+0

是的,正确的... –

回答

12

是,any()all()短路,一旦中止的结果是明确的:见docs

所有(迭代器)

返回true,如果所有元素的迭代是真实的(或者如果 迭代是空的)。等效于:

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

任何(迭代器)

返回真,如果可迭代的任何元素是真实的。如果迭代为 为空,则返回False。等效于:

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

我通常发现文档不好,但在这种情况下,它是无法清楚。非常感谢!这也正是我在考虑_lazy评估方面的想法。 _short-circuiting_有什么不同? –

+1

生成器表达式是懒惰的,它只在请求下一个项目时调用'some(x)'。 “任何/所有”短路,因为它只会请求项目直到结果清晰。你可以说'any([some(x)for x in range(5)])'仍然是短路的,但并不懒惰,因为列表理解导致'some'被调用到range的所有元素上x)''之前'任何'开始,但任何'仍然会停止检查输入列表尽快。 – chepner

4

虽然可迭代的第一个“真正的”元件上的all()any()功能短路,可迭代本身可以在一个非延迟方式构造。考虑下面的例子:

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

这将需要几秒钟在Python 2,以执行如range(10**8)构造10个** 8个元素的列表。相同的表达式在Python 3中立即运行,其中range()是懒惰的。

+1

善于观察 –

+0

我觉得这是令人困惑,因为我知道,'范围()'创建在python2的完整列表,但你把它包在一台发电机,这是懒 –

+0

@Chris_Rands:当您使用*发电机表达式*,如在上面的例子中,“for”表达式被立即评估。因此,即使在生成器运行之前,range()也会构造一个完整列表。 –

2

是的,这是懒惰的这表现在以下几点:

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(),即它短路评价。

第二次运行any()继续测试,直到序列耗尽。

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 
3

蒂姆正确提到,anyall做短期电路,但在你的代码,让他是利用generators。例如,下面的代码将不懒惰:

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

列表将被完全构造和计算的,然后才作为参数any通过。

发电机,而另一方面,有需求的是计算每个项目iterables。它们可以是expressionsfunctions,或者有时可以手动实现为惰性iterators

+0

不错的一个。谢谢! –