我希望使用 Python
all()
函数来帮助我计算某些内容,但如果 all()
在遇到 False
时不立即进行计算,则该内容可能需要更长的时间。我认为它可能是短路评估的,但我只是想确定一下。另外,有没有办法在 Python 中告诉函数如何被求值?
编者注:因为
any
和all
是函数,所以在调用它们之前必须对它们的参数进行求值。这通常会造成没有短路的印象 - 但它们仍然短路。要解决此问题,请传递 生成器表达式 或其他延迟计算的表达式,而不是序列。有关详细信息,请参阅 any() / all() 中的惰性函数求值。
是的,它短路了:
>>> def test():
... yield True
... print('one')
... yield False
... print('two')
... yield True
... print('three')
...
>>> all(test())
one
False
来自文档:
如果
iterable的所有元素都为 true(或者如果 iterable 为空),则返回True
。相当于:def all(iterable): for element in iterable: if not element: return False return True
所以当它
return
为False时,函数立即中断。
是的,
all
确实使用了短路评估。例如:
all(1.0/x < 0.5 for x in [4, 8, 1, 0])
=> False
当
x
到达列表中的1
时,当条件变为假时,上述过程停止。如果 all
没有短路,当 x
达到 0
时,我们会除以零。
确保您不要像我最初那样做,即在调用方法之前尝试使用短路来测试方法是否存在:
>>> class MyClass(object):
... pass
...
>>> a=MyClass()
>>> all([hasattr(a,'b'), a.b()])
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'b'
但是
>>> a=MyClass()
>>> hasattr(a,'b') and a.b() #doesn't evaluate a.b() as hasattr(a,'b') is false
False
在第一个代码片段中,Python 在将列表传递给 all() 之前对其进行计算,因此它仍然会引发异常。这与使用 list() 强制 all() 不要使用短路评估基本相同,如晨星的答案
在回答您是否可以告诉
all
进行短路评估或不进行短路评估的问题时,默认情况下它是短路的,但如果您不希望它这样,您可以这样做:
result = all(list(iterable))
尽管这可能有一个不受欢迎的特性,即整个列表将被加载到内存中。我无法想象除了使用与所有功能不同的功能之外您将如何避免这种情况。例如
result = reduce(lambda x,y: x and y, iterable)
result = min(iterable) # surprisingly similar to all; YMMV if iterable contains non-booleans