好吧,我可能只是有一个糟糕的工作日,但据我所知all()
应该短路根据文件。
all()
应等价于:
def all(iterable):
for element in iterable:
if not element:
return False
return True
也相当于菊花链and
。
所以下面的代码应该做同样的事情:
all((True, print('This should print and stop'), print("this shouldn't print")))
True and print('This should print and stop') and print("this shouldn't print")
然而最上面的一个会同时打印(即完全评估每个部分)但是底部短路了
这是Python(3.8.2)的错误还是我突然没有得到这个正确的?
Repl with example: https://repl.it/join/scxbpnhc-syntactical01
all
内部的迭代短路,但是每次调用print
都必须进行评估,以便在调用all
之前创建作为参数传递的tuple
。
def
语句,在Python中没有简单的方法来创建任意的惰性序列。你可以写
def foo():
yield True
yield print("This should print and stop")
yield print("this shouldn't print")
all(foo())
但是没有等价的纯表达式。您需要遍历一些来使用生成器表达式,例如
(x(y) for x, y in zip([id, print, print],
[True,
"This should print and stop",
"this shouldn't print"]))
会如你所愿。
>>> all(x(y) for x, y in zip([id, print, print], [True, "This should print and stop", "this shouldn't print"]))
This should print and stop
False
现在,print
在all
内部调用,而不是作为传递给all
的实参求值的一部分。
Python的all
接受一个可迭代对象作为参数
在你的问题中的例子的构造过程中,在这种情况下是一个元组,元组字面中的函数被调用,返回值插入到元组字面中;与:
>>> tup=(True, print('this'), False, print('not this'))
this
not this
如果你想要一个动态的集合形式你可以这样做:
def example_func(*args):
return args
g2all=(True, (print, 'this', 'and this'), False, (print, 'not this'), (example_func,1,2,3,4))
这依赖于这样一个事实,即您可以通过名称引用函数,如果没有()
调用操作符,则该函数尚未被调用:
>>> g2all
(True, (<built-in function print>, 'this', 'and this'), False, (<built-in function print>, 'not this'), (<function example_func at 0x10d0a9430>, 1, 2, 3, 4))
您可以在all
中使用生成器:
>>> all(f[0](*tuple(f[1:])) if isinstance(f, tuple) and callable(f[0]) else f for f in g2all)
this and this
False
当all
发现一个false值时,和函数的调用停止。