2010-02-19 103 views
8

我聽說過python中的延遲評估(例如here),它僅僅指的是lambdas如何僅在使用它時才被解釋器評估?或者這是一個合適的術語來描述,由於python的動態設計,它不會在運行時捕獲許多錯誤?Python中的延遲評估

或者我完全錯過了一些東西?

回答

8

迪特里希的回答是一個很好的,但我只想補充一點,推遲評價的最簡單的形式是if聲明:

if True: 
    x = 5 
else: 
    x = y # huh? what is y? 

此代碼正確分析和運行,雖然else條款是沒有意義的 - y未定義。 else子句只是被解析 - 所以它應該在語法上是有效的Python。這可實際用於一些簡單的代碼:

if stuff: 
    print stuff.contents 
else: 
    print "no stuff" 

在一個強類型語言,這將無法工作,因爲打字stuff.contents需要stuff是某種類型且具有contents屬性。在Python中,由於if中的陳述的延期評估,這不一定是正確的。 stuff可能是None,它顯然沒有任何屬性,解釋器只會採用else子句而不執行第一個。因此,這是有效的Python,甚至是一個成語,它使代碼更簡單。

Reference discussion

+7

我覺得你在第二個例子中混淆了類型系統和懶惰評估。 「強烈」類型的語言可以使用懶惰評估來做巧妙的技巧。例如。 Haskell有一個非常強大的靜態類型系統,有很多懶惰的評估!與Python不同,'if-then-else'必須進行類型檢查,但除此之外,評估是延遲的。例如,你可以編寫'如果True True then 5 undefined',並且編譯並運行得很好(結果如預期的那樣是5)。即使沒有用靜態語言進行類型檢查,你的'if-else'在Python中工作與評估策略無關。 –

14

延遲評估是表達式在需要時才進行評估的時間。在大多數語言中,您使用類似lambda的東西來完成此項工作。下面是顯示概念的一部分,一個人爲的例子:

def list_files(): 
    for fn in os.listdir('.'): 
     yield fn, lambda: open(fn, 'r').read() 


for fn, body in list_files(): 
    if fn.endswith('.txt'): 
     print body() 

這裏,list_files返回一堆文件名和一個「咚」(拉姆達不帶任何參數),返回文件的內容。 「thunk」是延期評估。使用的thunk允許你分開你的顧慮:for循環不需要知道如何讀文件

  • 的,所以list_files可以用list_ftp_fileslist_zip_archive更換。
  • list_files函數不需要知道哪些文件將被讀取。使用thunk時,它不必讀取每一個文件。

在正確的延期評估中,一旦您評估了「thunk」,它將用評估副本替換自己,因此評估兩次將不會比評估一次更好。還有其他方法可以完成同樣的事情,例如緩存值的類和對象。

延期評估是Sch​​eme中一個(相對)常見的習慣用法。在Haskell中,評估是默認推遲的,你不需要任何語法來完成它(有特殊的語法來關閉它)。

+4

拉姆達被推遲,但要小心保管,因爲他們不捕捉FN,你目前有他們:http://codepad.org/fXfIj364。另一個警告:http://codepad.org/poXS7nc2。 – 2010-02-19 05:50:48

+0

這是一個很好的觀點,也是我在Python編程時遠離lambda的原因之一。 –

+1

這就是爲什麼我更喜歡內聯函數+'functools.partial'來凍結參數:http:// codepad。org/fwxLbl7l – schlamar