在Python中短路all()语句

时间:2012-01-27 22:47:55

标签: python

有没有办法在Python中短路all()语句?

这样的事情:

return all([x != 0, 10 / x == 2, True, False, 7])
如果x为0,

不会返回错误?

4 个答案:

答案 0 :(得分:6)

这不起作用,因为在调用all之前评估列表(即其所有项目)。在这种特殊情况下,你最好的选择是这样的:

return x != 0 and 10 / x == 2 and True and False and 7

我假设您已经知道这一点,所以如果列表项没有硬编码,我会为您提供另一个更通用的解决方案:

return all(f() for f in [lambda: x != 0, lambda: 10 / x == 2, 
                         lambda: True, lambda: False, lambda: 7])

这样表达式只会在短路all内进行评估。

答案 1 :(得分:6)

如果您的代码在发生器中,那么您也可以通过这种方式短路:

def test(x):
    yield x != 0
    yield 10/x == 2
    yield True
    yield False
    yield 7

all(test(9))

答案 2 :(得分:3)

这不会像你想象的那样完全起作用,因为Python在将结果值传递给函数之前会计算其所有函数参数。换句话说,它会在调用10 / x == 2之前将all评估为单个值。 (与Mathematica形成对比,Mathematica将通过未评估的条件10 / x == 2并完全符合您的要求。)

最简单的事情是,只要你知道将把这个列表传递给all,就是使用Python的and运算符的短路功能:

return all([x != 0 and 10 / x == 2, True, False, 7])

或者,您可以重写数学条件,使其不会除以零,

return all([x != 0, 10 == 2 * x, True, False, 7])

(注意浮点除法问题)。

如果你真的想模仿Mathematica传递未评估条件的行为,那么我能想到的唯一方法就是传递一个可调用的对象,当你调用它时会评估条件。例如,您可以将所有列表元素转换为lambda函数:

return all(f() for f in [lambda: x != 0, lambda: 10 / x == 2,
                     lambda: True, lambda: False, lambda: 7])

如果您不想将所有内容转换为函数,我想您可以想出一些只会调用实际可调用内容的包装器:

return all(f() if callable(f) else f in [x != 0, lambda: 10 / x == 2,
                                                  True, False, 7])

但老实说,这似乎是一团糟(除非您在Python中编写CAS :-P)。

答案 3 :(得分:1)

是肯定的。如果你希望它对于x == 0:

是假的
all([x != 0, x!=0 and 10 / x == 2, True, False, 7])

只需确保任何值x都允许每个值。