像老大一样优化Python
admin
2023-07-31 00:48:29
0

我们应该忘掉一些小的效率问题,在 97% 的情况下是这么说的:过早优化是万恶之源。—— Donald Knuth

如果不首先想想这句Knuth的名言,就开始进行优化工作是不明智的。可是,你很快写出来加入一些特性的代码,可能会很丑陋,你需要注意了。这篇文章就是为这时候准备的。

那么接下来就是一些很有用的工具和模式来快速优化Python。它的主要目的很简单:尽快发现瓶颈,修复它们并且确认你修复了它们。

写一个测试

在你开始优化前,写一个高级测试来证明原来代码很慢。你可能需要采用一些最小值数据集来复现它足够慢。通常一两个显示运行时秒的程序就足够处理一些改进的地方了。

有一些基础测试来保证你的优化没有改变原有代码的行为也是很必要的。你也能够在很多次运行测试来优化代码的时候稍微修改这些测试的基准。

那么现在,我们来来看看优化工具把。

简单的计时器

计时器很简单,这是一个最灵活的记录执行时间的方法。你可以把它放到任何地方并且副作用很小。运行你自己的计时器非常简单,并且你可以将其定制,使它以你期望的方式工作。例如,你个简单的计时器如下:

1234567891011121314151617181920212223 import time def timefunc(f):    def f_timer(*args, **kwargs):        start = time.time()        result = f(*args, **kwargs)        end = time.time()        print f.__name__, \’took\’, end start, \’time\’        return result    return f_timer def get_number():    for x in xrange(5000000):        yield x @timefuncdef expensive_function():    for x in get_number():        i = x ^ x ^ x    return \’some result!\’ # prints \”expensive_function took 0.72583088875 seconds\”result = expensive_function()

当然,你可以用上下文管理来让它功能更加强大,添加一些检查点或者一些其他的功能:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 import time class timewith():    def __init__(self, name=\’\’):        self.name = name        self.start = time.time()     @property    def elapsed(self):        return time.time() self.start     def checkpoint(self, name=\’\’):        print \'{timer} {checkpoint} took {elapsed} seconds\’.format(            timer=self.name,            checkpoint=name,            elapsed=self.elapsed,        ).strip()     def __enter__(self):        return self     def __exit__(self, type, value, traceback):        self.checkpoint(\’finished\’)        pass def get_number():    for x in xrange(5000000):        yield x def expensive_function():    for x in get_number():        i = x ^ x ^ x    return \’some result!\’ # prints something like:# fancy thing done with something took 0.582462072372 seconds# fancy thing done with something else took 1.75355315208 seconds# fancy thing finished took 1.7535982132 secondswith timewith(\’fancy thing\’) as timer:    expensive_function()    timer.checkpoint(\’done with something\’)    expensive_function()    expensive_function()    timer.checkpoint(\’done with something else\’) # or directly\”crayon-v\”>timer.checkpoint(\’done with something else\’) # or directly׮题,在 97% 的情况下是这么说的:过早优化是万恶之源。—— Donald Knuth

如果不首先想想这句Knuth的名言,就开始进行优化工作是不明智的。可是,你很快写出来加入一些特性的代码,可能会很丑陋,你需要注意了。这篇文章就是为这时候准备的。

那么接下来就是一些很有用的工具和模式来快速优化Python。它的主要目的很简单:尽快发现瓶颈,修复它们并且确认你修复了它们。

写一个测试

在你开始优化前,写一个高级测试来证明原来代码很慢。你可能需要采用一些最小值数据集来复现它足够慢。通常一两个显示运行时秒的程序就足够处理一些改进的地方了。

有一些基础测试来保证你的优化没有改变原有代码的行为也是很必要的。你也能够在很多次运行测试来优化代码的时候稍微修改这些测试的基准。

那么现在,我们来来看看优化工具把。

简单的计时器

计时器很简单,这是一个最灵活的记录执行时间的方法。你可以把它放到任何地方并且副作用很小。运行你自己的计时器非常简单,并且你可以将其定制,使它以你期望的方式工作。例如,你个简单的计时器如下:

1234567891011121314151617181920212223 import time def timefunc(f):    def f_timer(*args, **kwargs):        start = time.time()        result = f(*args, **kwargs)        end = time.time()        print f.__name__, \’took\’, end start, \’time\’        return result    return f_timer def get_number():    for x in xrange(5000000):        yield x @timefuncdef expensive_function():    for x in get_number():        i = x ^ x ^ x    return \’some result!\’ # prints \”expensive_function took 0.72583088875 seconds\”result = expensive_function()

当然,你可以用上下文管理来让它功能更加强大,添加一些检查点或者一些其他的功能:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 import time class timewith():    def __init__(self, name=\’\’):        self.name = name        self.start = time.time()     @property    def elapsed(self):        return time.time() self.start     def checkpoint(self, name=\’\’):        print \'{timer} {checkpoint} took {elapsed} seconds\’.format(            timer=self.name,            checkpoint=name,            elapsed=self.elapsed,        ).strip()     def __enter__(self):        return self     def __exit__(self, type, value, traceback):        self.checkpoint(\’finished\’)        pass def get_number():    for x in xrange(5000000):        yield x def expensive_function():    for x in get_number():        i = x ^ x ^ x    return \’some result!\’ # prints something like:# fancy thing done with something took 0.582462072372 seconds# fancy thing done with something else took 1.75355315208 seconds# fancy thing finished took 1.7535982132 secondswith timewith(\’fancy thing\’) as timer:    expensive_function()    timer.checkpoint(\’done with something\’)    expensive_function()    expensive_function()    timer.checkpoint(\’done with something else\’) # or directlydiv class=\”crayon-line\” id=\”crayon-5812af18a580f561767955-47\”>timer = timewith(\’fancy thing\’)expensive_function()timer.

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...