【发布时间】:2015-06-15 13:59:02
【问题描述】:
一时兴起,我最近用timeit测试了这两种方法,看看哪种评估方法更快:
import timeit
"""Test method returns True if either argument is falsey, else False."""
def and_chk((a, b)):
if not (a and b):
return True
return False
def not_or_chk((a, b)):
if not a or not b:
return True
return False
...得到了这些结果:
VALUES FOR a,b -> 0,0 0,1 1,0 1,1
method
and_chk(a,b) 0.95559 0.98646 0.95138 0.98788
not_or_chk(a,b) 0.96804 1.07323 0.96015 1.05874
...seconds per 1,111,111 cycles.
效率差异在百分之一到百分之九之间,始终支持if not (a and b),这与我的预期相反,因为我知道if not a or not b 将评估其条款(if not a 然后@987654327 @) 按顺序运行if 块,一旦遇到真表达式(并且没有and 子句)。相比之下,and_chk 方法需要评估 两个 子句,然后才能将任何结果返回给包装它的 if not..。
然而,计时结果反驳了这种理解。那么,如何评估 if 条件?我完全清楚这样一个事实,即这种程度的微优化实际上(即使不是完全)毫无意义。我只是想了解 Python 是怎么做的。
为了完整起见,这就是我设置timeit...的方式...
cyc = 1111111
bothFalse_and = iter([(0,0)] * cyc)
zeroTrue_and = iter([(1,0)] * cyc)
oneTrue_and = iter([(0,1)] * cyc)
bothTrue_and = iter([(1,1)] * cyc)
bothFalse_notor = iter([(0,0)] * cyc)
zeroTrue_notor = iter([(1,0)] * cyc)
oneTrue_notor = iter([(0,1)] * cyc)
bothTrue_notor = iter([(1,1)] * cyc)
time_bothFalse_and = timeit.Timer('and_chk(next(tups))', 'from __main__ import bothFalse_and as tups, and_chk')
time_zeroTrue_and = timeit.Timer('and_chk(next(tups))', 'from __main__ import zeroTrue_and as tups, and_chk')
time_oneTrue_and = timeit.Timer('and_chk(next(tups))', 'from __main__ import oneTrue_and as tups, and_chk')
time_bothTrue_and = timeit.Timer('and_chk(next(tups))', 'from __main__ import bothTrue_and as tups, and_chk')
time_bothFalse_notor = timeit.Timer('not_or_chk(next(tups))', 'from __main__ import bothFalse_notor as tups, not_or_chk')
time_zeroTrue_notor = timeit.Timer('not_or_chk(next(tups))', 'from __main__ import zeroTrue_notor as tups, not_or_chk')
time_oneTrue_notor = timeit.Timer('not_or_chk(next(tups))', 'from __main__ import oneTrue_notor as tups, not_or_chk')
time_bothTrue_notor = timeit.Timer('not_or_chk(next(tups))', 'from __main__ import bothTrue_notor as tups, not_or_chk')
...然后使用.timeit(cyc) 运行每个timeit.Timer(..) 函数以发布结果。
【问题讨论】:
-
不是很明显吗?运算符较少。
-
它们应该以同样的方式短路:如果
a是False而不评估b,and应该停止,如果not a为真,or应该停止,不评估not b。 -
@Mephy,OP 没有征求编程建议。
-
Python 是一种语言规范,并且有一些实现可以解释您的源文件并运行它。既然您提到了 IDLE,我假设您使用的是 CPython,这是一个用 C 编写的 Python 解释器。如果他们想深入了解内部结构以理解您的结果,这可能会有所帮助。
-
dis模块,它显示 Python 字节码(一种高级汇编语言,如果您不熟悉的话)可能会有所帮助。试试import dis; print(dis.dis(f)),f是你的函数。
标签: python python-2.7 if-statement logical-operators micro-optimization