尽管运行速度慢是Python的固有特性,但是大多数时候我们使用Python就意味着放弃对性能的追求。但是,即使是用纯Python完成同样的任务,老手写的代码可能比菜鸟写的代码块大几倍,甚至几十倍(这里不考虑算法因素,只考虑语言因素)).很多时候,我们把自己代码运行慢的原因归咎于python天生就慢,于是心安理得的放弃了深入探索。但是,真的是这样吗?面对python代码,你是否分析过以下问题:程序运行速度有多快?程序运行时间的瓶颈在哪里?你能做一些改进来提高运行速度吗?为了更好的理解python程序,我们需要一套工具,可以记录代码的运行时间,并生成性能分析报告,方便深入理解代码,从而进行有针对性的优化(本文重点介绍代码性能分析,而不是如何优化)。谁快谁慢假设有一个字符串,你想用字符'-'替换其中的空格,用python实现很简单,下面是四种解决方案:defslowest_replace():replace_list=[]fori,charinenumerate(orignal_str):c=charifchar!=""else"-"replace_list.append(c)return"".join(replace_list)defslow_replace():replace_str=""fori,charinenumerate(orignal_str):c=charifchar!=""else"-"replace_str+=creturnreplace_strdeffast_replace():return"-".join(orignal_str.split())deffastest_replace():returnorignal_str.replace("","-")这些的效率是多少四种方案,哪种方案比较慢??这是个问题!时间断点最直接的思路就是记录replace函数开始前的时间,记录程序结束后的时间,计算出时间差作为程序运行时间。Python提供了时间模块,time.clock()在Unix/Linux下返回CPU时间(以秒为单位,以浮点数表示),在Win下返回实时时间(Wall-clocktime),以秒为单位。由于替换函数的耗时可能很短,这里考虑执行10万次,然后检查不同函数的效率。我们的性能分析辅助函数如下:def_time_analyze_(func):fromtimeimportclockstart=clock()foriinrange(exec_times):func()finish=clock()print"{:<20}{:10.6}s".format(func.__name__+":",finish-start)这样你就可以明白上面程序的运行时间了:第一个解的时间是第四个解的45倍多,令人吃惊!同样是用python代码完成同样的功能,耗时差别很大。为了避免每次都在程序的开头和结尾插入时间断点,然后计算耗时,可以考虑实现一个上下文管理器,具体代码如下:classTimer(object):def__init__(self,verbose=False):self.verbose=详细def__enter__(self):self.start=clock()returnselfdef__exit__(self,*args):self.end=clock()self.secs=self.end-self.startself.msecs=self.secs*1000#millisecsifself.verbose使用:print'elapsedtime:%fms'%self.msecs时,只需要将测量时间的代码段放到with语句中即可,具体使用示例在要旨。在timeit上手动插入断点的方法非常原始,使用起来也不是那么方便,即使使用上下文管理器实现,也还是有些繁琐。幸运的是,Python提供了timeit模块来测试代码块的运行时间。它既提供了命令行界面又可以在代码文件中使用。CLI可以这样使用:$python-mtimeit-n1000000'"Iliketoreading.".replace("","-")'1000000loops,bestof3:0.253usecperloop$python-mtimeit-s'orignal_str="Iliketoreading."''"-".join(orignal_str.split())'1000000loops,bestof3:0.53usecperloop具体参数可以配合命令python-mtimeit-h查看帮助。常用的选项如下:-sS,--setup=S:用于初始化语句中的变量,只运行一次;-nN,--number=N:执行语句的次数,默认number会选择一个合适的;-rN,--repeat=N:重复测试的次数,默认3次;Python接口可以使用下面的程序来测试四个replace函数的运行(完整的测试程序可以在gist中找到):def_timeit_analyze_(func):fromtimeitimportTimert1=Timer("%s()"%func.__name__,"from__main__import%s"%func.__name__)print"{:<20}{:10.6}s".format(func.__name__+":",t1.timeit(exec_times))运行结果如下:Python的timeit提供timeit.Timer()类,该类构造方法如下:Timer(stmt='pass',setup='pass',timer=
