如何在Python中实现延迟评估?几个简单的例子:
>>> def foo(x):
... print(x)
... return x
...
>>> random.choice((foo('spam'), foo('eggs')))
spam
eggs
'eggs'
上面,我们并不需要评估这个元组的所有项目,以便选择一个。在下面,除非查找键实际上从dict中丢失,否则不需要计算默认的foo()
:
>>> d = {1: "one"}
>>> d.get(2, foo("default"))
default
'default'
>>> d.get(1, foo("default"))
default
'one'
我正在寻找一种Pythonic方法来重构像上面这样的例子,以便懒惰地评估。
答案 0 :(得分:7)
在Python中进行延迟评估的标准方法是使用generators。
def foo(x):
print x
yield x
random.choice((foo('spam'), foo('eggs'))).next()
顺便说一句。 Python也允许generator expressions,因此下面的行不会预先计算任何内容:
g = (10**x for x in xrange(100000000))
答案 1 :(得分:5)
您可以使用partial
( - 应用函数):
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
可用于在以后生成一系列值。
答案 2 :(得分: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")))()
答案 3 :(得分:0)
另一个解决方案是构建并返回一个callable,它封装了你想要对随机选择执行的动作。
def foo(sequence):
def chooser():
choice = random.choice(sequence)
print choice
return choice
return chooser
>>> c = foo(['spam', 'eggs', 'ham'])
>>> c()
... ham
>>> 'ham'