避免或延迟评估可能未使用的东西

问题描述 投票:4回答:4

如何在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方法来重构像上面这样的例子,以便懒惰地评估。

python lazy-evaluation
4个回答
7
投票

在Python中进行延迟评估的标准方法是使用generators

def foo(x):
    print x
    yield x

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

BTW。 Python也允许使用generator expressions,因此下面的行不会预先计算任何东西:

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

5
投票

你可以使用apartial(-ly applied function):

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

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

当你需要一个默认的dict时,你可以使用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
投票

另一个解决方案是构建并返回一个callable,它封装了您想要对随机选择执行的操作。

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

>>> c = foo(['spam', 'eggs', 'ham'])
>>> c()
... ham
>>> 'ham'
© www.soinside.com 2019 - 2024. All rights reserved.