在Python中短路all()语句
有没有办法让Python中的all()语句提前结束?
比如像这样:
return all([x != 0, 10 / x == 2, True, False, 7])
如果x是0的话,这样不会报错吗?
4 个回答
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写一个计算机代数系统 :-P)。
6
如果你的代码是在一个生成器里,那么你也可以用这种方式来快速跳过一些操作:
def test(x):
yield x != 0
yield 10/x == 2
yield True
yield False
yield 7
all(test(9))
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
中被计算。