假设我有一个函数getQ(x)
,它返回一些数字并且速度很慢。现在,如果我这样做:
x = 10
x = getQ(x) if getQ(x) >= 0 else 0
在这种情况下, getQ
会被执行两次吗?
这是:
x = getQ(x)
x = x if x >= 0 else 0
更快?
如果是这样,对于这种情况,是否会有更优雅的单线?
答案 0 :(得分:5)
是的,如果结果是非负的话,getQ
会被调用两次,所以第二种情况肯定会更快。
在这种特殊情况下,您可以编写x = max(getQ(x), 0)
。 "将军"您正在寻找的解决方案就像是
x = (lambda x: x if x >= 0 else 0)(getQ(x))
我不建议在实际代码中使用它,但它允许您绑定一个名称,同时仍保留一个表达式。
答案 1 :(得分:1)
您可以使用dis
模块,并清楚地看到在第一种情况下将调用该函数两次。
def fun1():
...: x = sqrt(10) if sqrt(10)>=0 else 0
...:
dis.dis(fun1)
2 0 LOAD_GLOBAL 0 (sqrt)
3 LOAD_CONST 1 (10)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair) // First Call
9 LOAD_CONST 2 (0)
12 COMPARE_OP 5 (>=)
15 POP_JUMP_IF_FALSE 30
18 LOAD_GLOBAL 0 (sqrt)
21 LOAD_CONST 1 (10)
24 CALL_FUNCTION 1 (1 positional, 0 keyword pair) // Second Call
27 JUMP_FORWARD 3 (to 33)
>> 30 LOAD_CONST 2 (0)
>> 33 STORE_FAST 0 (x)
36 LOAD_CONST 0 (None)
39 RETURN_VALUE
def fun2():
x = sqrt(10)
x = x if x>=10 else 0
dis.dis(fun2)
2 0 LOAD_GLOBAL 0 (sqrt)
3 LOAD_CONST 1 (10)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair) // Single call
9 STORE_FAST 0 (x)
3 12 LOAD_FAST 0 (x)
15 LOAD_CONST 1 (10)
18 COMPARE_OP 5 (>=)
21 POP_JUMP_IF_FALSE 30
24 LOAD_FAST 0 (x)
27 JUMP_FORWARD 3 (to 33)
>> 30 LOAD_CONST 2 (0)
>> 33 STORE_FAST 0 (x)
36 LOAD_CONST 0 (None)
39 RETURN_VALUE