Den*_*nis 16 python performance
一位朋友(低级技能级别的娱乐python脚本编写者)让我查看一些代码.我注意到他有7个单独的陈述,基本上说.
if ( a and b and c):
do something
Run Code Online (Sandbox Code Playgroud)
陈述a,b,c都测试了它们的相等或缺乏设定值.当我看到它时,我发现由于测试的性质,我可以将整个逻辑块重写为2个分支,从不超过3个深度并且很少超过第一个级别(进行最罕见的测试)第一).
if a:
if b:
if c:
else:
if c:
else:
if b:
if c:
else:
if c:
Run Code Online (Sandbox Code Playgroud)
对我来说,从逻辑上讲,如果你做的更少,更简单的测试更快失败并继续前进,它似乎应该更快.我真正的问题是
1)当我说if if时,如果if为真,那么else会被完全忽略吗?
2)理论上会
如果(a和b和c)
花三倍于单独的if语句会花多少时间?
Set*_*son 33
ifelse如果计算结果为true,则语句将跳过括号中的所有内容.应该指出的是,担心这类问题,除非每个程序执行数百万次,否则称为"过早优化",应该避免.如果您的代码使用三个if (a and b and c)语句更清晰,则应将其保留.
Ign*_*ams 19
码:
import dis
def foo():
if ( a and b and c):
pass
else:
pass
def bar():
if a:
if b:
if c:
pass
print 'foo():'
dis.dis(foo)
print 'bar():'
dis.dis(bar)
Run Code Online (Sandbox Code Playgroud)
输出:
foo():
4 0 LOAD_GLOBAL 0 (a)
3 JUMP_IF_FALSE 18 (to 24)
6 POP_TOP
7 LOAD_GLOBAL 1 (b)
10 JUMP_IF_FALSE 11 (to 24)
13 POP_TOP
14 LOAD_GLOBAL 2 (c)
17 JUMP_IF_FALSE 4 (to 24)
20 POP_TOP
5 21 JUMP_FORWARD 1 (to 25)
>> 24 POP_TOP
7 >> 25 LOAD_CONST 0 (None)
28 RETURN_VALUE
bar():
10 0 LOAD_GLOBAL 0 (a)
3 JUMP_IF_FALSE 26 (to 32)
6 POP_TOP
11 7 LOAD_GLOBAL 1 (b)
10 JUMP_IF_FALSE 15 (to 28)
13 POP_TOP
12 14 LOAD_GLOBAL 2 (c)
17 JUMP_IF_FALSE 4 (to 24)
20 POP_TOP
13 21 JUMP_ABSOLUTE 29
>> 24 POP_TOP
25 JUMP_ABSOLUTE 33
>> 28 POP_TOP
>> 29 JUMP_FORWARD 1 (to 33)
>> 32 POP_TOP
>> 33 LOAD_CONST 0 (None)
36 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
因此,虽然设置相同,但组合表达式的清理速度更快,因为它只在堆栈上留下一个值.
如果你担心 b 或 c 是被调用的函数而不是被评估的变量,那么这段代码表明短路是你的朋友:
a = False
def b():
print "b was called"
return True
if a and b():
print "this shouldn't happen"
else:
print "if b was not called, then short-circuiting works"
Run Code Online (Sandbox Code Playgroud)
印刷
if b was not called, then short-circuiting works
Run Code Online (Sandbox Code Playgroud)
但是,如果您有执行此操作的代码:
a = call_to_expensive_function_A()
b = call_to_expensive_function_B()
c = call_to_expensive_function_C()
if a and b and c:
do something...
Run Code Online (Sandbox Code Playgroud)
那么您的代码仍在调用所有 3 个昂贵的函数。最好让 Python 成为 Python:
if (call_to_expensive_function_A() and
call_to_expensive_function_B() and
call_to_expensive_function_C())
do something...
Run Code Online (Sandbox Code Playgroud)
它只会根据需要调用尽可能多的昂贵函数来确定整体条件。
编辑
您可以使用all内置的来概括这一点:
# note, this is a list of the functions themselves
# the functions are *not* called when creating this list
funcs = [function_A, function_B, function_C]
if all(fn() for fn in funcs):
do something
Run Code Online (Sandbox Code Playgroud)
现在,如果您必须添加其他功能,或者想要对它们重新排序(可能function_A非常耗时,并且您可以通过过滤失败function_B或function_C首先的案例受益),您只需更新funcs列表。 all做短路就像你已经拼出 if as 一样if a and b and c。(如果函数是“或”在一起的,请改用any内置函数。)
| 归档时间: |
|
| 查看次数: |
19890 次 |
| 最近记录: |