2012-03-21 66 views
4

如何在python中完成這種事情?這是稱爲懶惰評估還是我把名字與其他東西混合?例如:避免或延遲評估不可用的東西

>>> def foo(x): 
... print x 
... return x 
... 
>>> random.choice((foo('spam'), foo('eggs'))) 
spam 
eggs 
'eggs' 

但我們並不真的需要評估所有這些項目,或者我們是否?

這工作,但我覺得它是相當難看:

>>> random.choice((lambda: foo('spam'), lambda: foo('eggs')))() 
eggs 
'eggs' 

另一個例子是使用dict.get(key, somedefault())其中somedefault並不真正需要被調用,除非key not in dict

+3

是的,你所描述的一般稱爲懶惰評估。 – adelphus 2012-03-21 10:50:10

+1

這裏明顯的答案只是在做出選擇後應用''foo()''函數。此外,當您使用迭代器時,請記住使用列表中的生成器進行惰性評估。 – 2012-03-21 10:52:51

回答

5

可以使用partial(-ly應用功能):

import random 
def foo(x): 
    print x 
    return x 

from functools import partial 
print random.choice((partial(foo,'spam'), partial(foo,'eggs')))() 

當你需要使用默認的字典,你可以使用defaultdict

from collections import defaultdict 
d = defaultdict(somedefault) 
print d[k] # calls somedefault() when the key is missing 

Python是不是偷懶語言,對懶惰沒有特別的支持。當你想稍後生成一個單獨的值時,你必須將它包裝在一個函數中。另外,generators可用於在稍後生成一系列值。

1

除非你放棄使用一個更現實的例子,我會做這樣的:

>>> def foo(x): 
...  print x 
...  return x 
... 
>>> foo(random.choice(("spam", "eggs"))) 
spam 
'spam' 

但是你可以創建一個輔助類是這樣的:

class LazyEval(object): 
    def __init__(self, func, *args, **kwargs): 
     self.func = func 
     self.args = args 
     self.kwargs = kwargs 

    def __call__(self): 
     return self.func(*self.args, **self.kwargs) 

random.choice((LazyEval(foo, "spam"), LazyEval(foo, "eggs")))() 
0

只要做到這一點懶:

random.choice((lambda: foo('spam'), lambda: foo('eggs')))() 
+0

不幸的是,標準的'dict.get(k,d)'不是基於更高階的機制。你可以編寫你自己的字典類,但是;-) – Alfe 2012-03-21 10:54:34

+0

如果你發現lambda語法醜陋,讓你的foo()函數返回適當的lambda。但是懶惰(沒有放棄真正需要做的事情)意味着寫下必須完成的事情(以防萬一)。使用lambda就是這樣:它說明需要做什麼,以防萬一。它不會立即執行。這就是懶惰的定義。 – Alfe 2012-03-21 11:29:26

7

在Python中執行懶惰評估的標準方法是使用generators

def foo(x): 
    print x 
    yield x 

random.choice((foo('spam'), foo('eggs'))).next() 

順便說一句。蟒蛇也允許generator expressions,所以下面的線不會預先計算什麼:

g = (10**x for x in xrange(100000000)) 
0

另一種解決方案是建立並返回封裝要在隨機選擇執行操作的調用。

def foo(sequence): 
    def chooser(): 
     choice = random.choice(sequence) 
     print choice 
     return choice 
    return chooser 

>>> c = foo(['spam', 'eggs', 'ham']) 
>>> c() 
... ham 
>>> 'ham'