Python3.8 `all()` 没有短路

Python3.8 `all()` not short circuiting

好吧,我可能只是今天工作不顺利,但据我所知 all() 应该短路 according to the docs

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) 的错误还是我突然没弄对?

回复示例: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())

但是没有等价的纯表达式。您需要迭代 something 才能使用生成器表达式,例如

(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

现在,printall 内部被调用,而不是作为评估传递给 all 的参数的一部分。

Python的all拿一个iterable as an argument

在构建您问题中的示例(在本例中为元组)期间,调用元组文字中的函数,并将 return 值插入到元组文字中;无异于:

>>> tup=(True, print('this'), False, print('not this'))
this
not this

如果你想要assemble的形式你可以这样做:

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 找到 Falsie 值时函数调用停止。