我最近开始学习编程(用Python)。我有两段使用while循环的代码:
a=100000000
#piece of code 1
while a > 0:
a-=10
print("done")
#piece of code 2
while True:
a-=10
if a <= 0:
print("done")
break两者在功能上是等价的,即它们执行的任务本质上是相同的。出于好奇,我使用time模块使用这两个版本的while循环记录了执行此操作所需的时间。研究结果如下:
代码1: 0.99 s
代码2: 0.89 s
它们显示了基本相同的性能,尽管代码2的部分效率略高一些。这是可以的,因为即使对于非常大的数字,这种差异基本上也是无关紧要的。但是,这对我来说有点出乎意料,因为我认为第一个while循环执行的操作较少。有人能解释一下为什么第二段代码更高效吗?
发布于 2019-11-03 21:00:22
我把这些片段放在两个函数中:
def first():
a=100000000
while a > 0:
a-=10
def second():
a=100000000
while True:
a-=10
if a <= 0:
break然后使用了timeit.timeit,实际上是second一直被计时为花费更长的时间(尽管差异非常小)。
from timeit import timeit
timeit(first, number=100)
timeit(second, number=100)然后,通过从dis文档复制示例来检查字节码。这表明字节码对于这两个代码段几乎是相同的,唯一的区别是操作码的排序方式,并且second包含一个额外的指令,即BREAK_LOOP。
import dis
from collections import Counter
first_bytecode = dis.Bytecode(first)
for instr in first_bytecode:
print(instr.opname)
second_bytecode = dis.Bytecode(second)
for instr in second_bytecode:
print(instr.opname)
# easier to compare with Counters
first_b = Counter(x.opname for x in first_bytecode)
sec_b = Counter(x.opname for x in second_bytecode)最后,人们可能会认为顺序可能会产生不同(而且可能),但为了进行公平的比较,second应该首先检查中断条件,然后再从a中减去。然后考虑第三项职能:
def third():
a=100000000
while True:
if a <= 0:
break
a-=10将third的字节码进行比较,您会发现它的排序实际上与first的字节码相同,唯一的区别是阻塞在中间某个位置的单个BREAK_LOOP。
如果有什么希望的话,我希望这向您展示一个操作码的执行对于代码的总体性能来说是多么的微不足道。我认为唐纳德·克努斯的不朽的话语特别适合这一场合:
我们应该忘记小效率,说大约97%的时候:过早的优化是所有邪恶的根源。
https://stackoverflow.com/questions/58684208
复制相似问题