Python:如何测试IF语句对Dictionary Case语句的效率?

时间:2015-03-12 03:04:17

标签: python if-statement case

我希望能够在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上运行。

提前致谢。

1 个答案:

答案 0 :(得分:2)

听起来你的主要优化领域不是这个陈述。

然而,出于好奇,我还是检查了它。在您链接的问题中给出的直观答案是python词典被实现为哈希表。查找应该使用项目数在O(1)附近缩放。如果你所展示的陈述将在O(n)处缩放,因为每个陈述将按顺序进行。通过使用每个函数的函数运行1000个随机数,有2到1000个选项,我得到以下时间(y刻度是每个选项的秒数,并且是对数刻度)。如果链是蓝色,则dict查找为绿色。 x标度是可能的选择数量:

enter image description here

可以看出,查找比if语句链更快。

即使对于短链,在此代码中,查找仍然更快或大致相同:

enter image description here

但请注意这里的时间。我们在计算机上每次选择亚微秒范围内的时间:大约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)+" ",