2016-09-06 252 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

不錯的一個。謝謝! –