我想知道为什么try-except比下面程序中的if慢。
def tryway():
try:
while True:
alist.pop()
except IndexError:
pass
def ifway():
while True:
if alist == []:
break
else:
alist.pop()
if __name__=='__main__':
from timeit import Timer
alist = range(1000)
print "Testing Try"
tr = Timer("tryway()","from __main__ import tryway")
print tr.timeit()
print "Testing If"
ir = Timer("ifway()","from __main__ import ifway")
print ir.timeit()
我得到的结果很有趣。
Testing Try
2.91111302376
Testing If
0.30621099472
任何人都可以解释为什么尝试这么慢?
答案 0 :(得分:41)
你只设置一次alist。第一次调用“tryway”会清除它,然后每次连续调用都不会执行任何操作。
def tryway():
alist = range(1000)
try:
while True:
alist.pop()
except IndexError:
pass
def ifway():
alist = range(1000)
while True:
if alist == []:
break
else:
alist.pop()
if __name__=='__main__':
from timeit import Timer
print "Testing Try"
tr = Timer("tryway()","from __main__ import tryway")
print tr.timeit(10000)
print "Testing If"
ir = Timer("ifway()","from __main__ import ifway")
print ir.timeit(10000)
>>> Testing Try
>>> 2.09539294243
>>> Testing If
>>> 2.84440898895
答案 1 :(得分:4)
在大多数语言中,异常处理通常很慢。大多数编译器,解释器和VM(支持异常处理)将异常(语言习语)视为异常(不常见)。性能优化涉及权衡,快速制作异常通常意味着语言的其他区域会受到影响(无论是性能还是设计简单)。
在更技术层面,异常通常意味着VM /解释器(或运行时执行库)必须保存一堆状态并开始关闭函数调用堆栈上的所有状态(称为展开),直到找到有效捕获(除外)的点。
或者从不同的角度来看,程序在发生异常并且“调试器”接管时停止运行。此调试器在堆栈中搜索(调用函数数据)以查找与异常匹配的catch。如果它找到一个,它会清理一些东西并在那时将控制权返回给程序。如果找不到,那么它会将控制权返回给用户(可能是以交互式调试器或python REPL的形式)。
答案 2 :(得分:3)
如果你真的对速度感兴趣,那么你的两位参赛者都可以减轻体重。
while True:
慢于while 1:
- True
是一个加载和测试的全局“变量”; 1
是一个常量,编译器执行测试并发出无条件跳转。
while True:
是多余的。将while / if / break折叠起来:while alist != []:
while alist != []:
编写while alist:
试试这个:
def tryway2():
alist = range(1000)
try:
while 1:
alist.pop()
except IndexError:
pass
def ifway2():
alist = range(1000)
while alist:
alist.pop()
`
答案 3 :(得分:2)
仍然有更快的迭代方式,虽然有时我们希望列表实际上是shirink所以我们知道剩下多少。然后alist应该是生成器的参数。 (John也适用于while alist:
)我将函数作为生成器并使用了列表(ifway())等,因此这些值实际上是在函数外使用的(甚至没有使用过):
def tryway():
alist = range(1000)
try:
while True:
yield alist.pop()
except IndexError:
pass
def whileway():
alist = range(1000)
while alist:
yield alist.pop()
def forway():
alist = range(1000)
for item in alist:
yield item
if __name__=='__main__':
from timeit import Timer
print "Testing Try"
tr = Timer("list(tryway())","from __main__ import tryway")
print tr.timeit(10000)
print "Testing while"
ir = Timer("list(whileway())","from __main__ import whileway")
print ir.timeit(10000)
print "Testing for"
ir = Timer("list(forway())","from __main__ import forway")
print ir.timeit(10000)
J:\test>speedtest4.py
Testing Try
6.52174983133
Testing while
5.08004508953
Testing for
2.14167694497
答案 4 :(得分:0)
不确定,但我认为它是这样的:while true遵循正常的指令行,这意味着处理器可以管道并做各种好事。异常直接跳过所有这些,因此VM需要特别处理它,这需要时间。
答案 5 :(得分:0)
只是想把它扔到混合中:
我在下面尝试了以下脚本,这似乎表明处理异常比处理else
语句要慢:
import time
n = 10000000
l = range(0, n)
t0 = time.time()
for i in l:
try:
i[0]
except:
pass
t1 = time.time()
for i in l:
if type(i) == list():
print(i)
else:
pass
t2 = time.time()
print(t1-t0)
print(t2-t1)
给出:
5.5908801555633545
3.512694835662842
所以,(尽管我知道有人可能会评论使用time
而不是timeit
),但使用try / except in循环似乎会减慢约60%。因此,在经历数十亿项的for循环时,最好与if/else
一起使用。
答案 6 :(得分:-1)