【发布时间】:2021-01-13 08:41:34
【问题描述】:
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 的力量 短路,这意味着一旦可迭代的第一个元素为真,它就会中断。如果函数调用很昂贵,那么预先评估所有函数是一个很大的损失,并且是对any 的这种能力的浪费。从某种意义上说,这可以称为 Python 陷阱,因为尝试利用 any 的这一特性的用户可能会出乎意料,并且因为 any 通常被认为只是链接 @987654337 序列的另一种语法方式@ 声明。但any 只是短路,而不是懒惰,这就是区别。
any is accepting an iterable。因此,应该有一种方法可以创建一个迭代器,它不会预先评估其元素,而是将未评估的元素传递给 any,并让它们仅在 any 内部进行评估,以实现完全惰性评估。
所以,问题是:我们如何使用any 进行真正的惰性函数评估?这意味着:我们如何在不预先评估所有函数调用的情况下创建any 可以使用的函数调用的迭代器?
【问题讨论】:
-
在 Python 中有各种各样的迭代器产生东西。例如
map():any(map(func, ('s', 't')))。大多数人似乎在 Python3 中遇到了相反的问题——他们想要列表输出,而 Python 为他们提供了生成器和地图! -
这与
any无关。评估发生在构建列表时。
标签: python lazy-evaluation any short-circuiting