Python中的逻辑运算符是惰性的。定义如下:
def func(s):
print(s)
return True
调用or
运算符
>>> func('s') or func('t')
's'
仅计算第一个函数调用,因为or
识别表达式的计算结果为
True
,与第二个函数调用的返回值无关and
的行为与此类似
但是,当以以下方式使用any()
(类似地:all()
)时:
>>> any([func('s'), func('t')])
's'
't'
所有函数调用都会求值,因为内部列表是在any
开始迭代其项的布尔值之前首先构造的。当我们省略列表结构而只写
>>> any(func('s'), func('t'))
's'
't'
这样我们就失去了any
短路的能力,这意味着一旦iterable的第一个元素是真的,它就会断开。如果函数调用很昂贵,那么预先评估所有函数将是一个巨大的损失,并且浪费了any
的这种能力。从某种意义上说,我们可以称之为Python gotcha,因为对于试图利用any
这一特性的用户来说,这可能是意外的,而且any
通常被认为只是链接or
语句序列的另一种语法方式。但是any
只是短路,而不是懒惰,这就是这里的区别
^{any
,只允许它们在any
内部进行计算,以实现完全惰性的计算
因此,问题是:我们如何将any
用于真正的惰性函数求值?这意味着:我们如何能够在不预先计算所有函数调用的情况下,生成any
可以使用的函数调用迭代器
我们可以使用generator expression,分别传递函数及其参数,并仅在生成器中求值,如下所示:
对于具有不同签名的不同函数,这可能如下所示:
这样,
any
将在生成器中的一个函数调用求值为True
时停止调用生成器中的next()
元素,这意味着函数求值是完全惰性的wjandrea在评论中提到了另一种推迟函数评估的简洁方法:我们也可以使用lambda expressions,如下所示:
相关问题 更多 >
编程相关推荐