我希望能够在Python中测试IF语句对字典案例语句hack的效率。由于没有case语句,我目前正在使用字典方法。它看起来像......
self.options = {"0": self.racerOne,
"1": self.racerTwo,
"2": self.racerThree,
"3": self.racerFour,
"0f": self.racerFinish,
"1f": self.racerFinish,
"2f": self.racerFinish,
"3f": self.racerFinish,
"x": self.emptyLine,
"t": self.raceTime,
"G": self.letsGo,
"CD": self.countDown,
"C": self.emptyLine,
}
现实世界的数据会有所不同,但我有办法进行受控测试,在6.4秒内读取688行流数据。
我也读过这篇文章:Python Dictionary vs If Statement Speed我也将查看cProfile方法。
与字典选项相比,有没有人对如何准确测量IF语句有任何其他建议?通过高效,我猜这意味着使用最少的处理能力,可以更好地跟上流。
在6.4秒内,我读取每行流数据,解析,评估,然后实时显示。我不认为在Win或OSX系统上运行我的应用程序会有太大的不同,但它也必须在处理能力有限的Raspberry Pi上运行。
提前致谢。
答案 0 :(得分:2)
听起来你的主要优化领域不是这个陈述。
然而,出于好奇,我还是检查了它。在您链接的问题中给出的直观答案是python词典被实现为哈希表。查找应该使用项目数在O(1)附近缩放。如果你所展示的陈述将在O(n)处缩放,因为每个陈述将按顺序进行。通过使用每个函数的函数运行1000个随机数,有2到1000个选项,我得到以下时间(y刻度是每个选项的秒数,并且是对数刻度)。如果链是蓝色,则dict查找为绿色。 x标度是可能的选择数量:
可以看出,查找快,多比if语句链更快。
即使对于短链,在此代码中,查找仍然更快或大致相同:
但请注意这里的时间。我们在计算机上每次选择亚微秒范围内的时间:大约600ns,选择次数少。此时,开销可能来自函数调用这样简单的事情。另一方面,如果您有大量可能的选择,最好使用的应该是非常明确的。
上面的代码如下。它使用numpy来跟踪所有时间。对于像这样的简单计时问题,通常最简单的方法是使用time.time()来获取您想要做的事情之前和之后的时间值。对于速度非常快的东西,你需要循环多次并平均花费一些时间。
我应该补充说,我创建if语句链的方式是温和的邪恶。这样做(使用exec语句)可能在某种程度上没有以相同的方式进行优化:我不是python内部的专家。
import numpy as np
import time
def createdictfun(n):
optdict = { x: 2*x for x in range(0,n) }
def dictfun(x):
return optdict[x]
return dictfun
def createiffun(n):
s="def iffun(x):\n"
s+=" if x==0: return 0\n"
for i in range(1,n):
s+=" elif x=={}: return {}\n".format(i,i*2)
s+=" else: raise ValueError\n"
exec s
return iffun
ntry=10
maxchoice=1000
trialsize=1000
ifvals=np.zeros((maxchoice,2))
dictvals=np.zeros((maxchoice,2))
ns=np.arange(1,maxchoice)
for n in ns:
ift = np.zeros(ntry)
dictt = np.zeros(ntry)
vals=np.random.randint(0,n,size=trialsize)
iffun = createiffun(n)
dictfun = createdictfun(n)
for trial in range(0,ntry):
ts=time.time()
for x in vals:
iffun(x)
ift[trial]=time.time()-ts
ts=time.time()
for x in vals:
dictfun(x)
dictt[trial]=time.time()-ts
ifvals[n,0]=np.mean(ift)/trialsize
ifvals[n,1]=np.std(ift)/trialsize
dictvals[n,0]=np.mean(dictt)/trialsize
dictvals[n,1]=np.std(dictt)/trialsize
print str(n)+" ",