好吧,我正在阅读这篇文章然后我遇到了一个代码:
jokes=range(1000000) domain=[(0,(len(jokes)*2)-i-1) for i in range(0,len(jokes)*2)]
我认为在列表理解之外计算len(笑话)的值不是更好吗?
好吧,我尝试了它并计时三个代码
jv@Pioneer:~$ python -m timeit -s 'jokes=range(1000000);domain=[(0,(len(jokes)*2)-i-1) for i in range(0,len(jokes)*2)]' 10000000 loops, best of 3: 0.0352 usec per loop jv@Pioneer:~$ python -m timeit -s 'jokes=range(1000000);l=len(jokes);domain=[(0,(l*2)-i-1) for i in range(0,l*2)]' 10000000 loops, best of 3: 0.0343 usec per loop jv@Pioneer:~$ python -m timeit -s 'jokes=range(1000000);l=len(jokes)*2;domain=[(0,l-i-1) for i in range(0,l)]' 10000000 loops, best of 3: 0.0333 usec per loop
观察第一个和第二个之间的边际差异2.55%让我觉得 - 是第一个列表理解
domain=[(0,(len(jokes)*2)-i-1) for i in range(0,len(jokes)*2)]
python内部优化?或者2.55%是一个足够大的优化(假设len(笑话)= 1000000)?
如果是这样 - Python中的其他隐式/内部优化是什么?
有什么developer's rules of thumb for optimization in Python
?
EDIT1:由于大多数的答案都是"不优化,做到这一点后,如果其慢",我得到了一些提示和链接从Triptych
与Ali A
该做的.我会稍微改变一下这个问题,并要求不要做.
我们能否从面对" 缓慢 "的人那里获得一些经验,问题是什么以及如何纠正?
编辑2:对于那些没有在这里的人是一个有趣的读物
编辑3:有timeit
问题的错误用法请参阅dF的答案,以确定正确的用法,以及三个代码的时间安排.
你没有timeit
正确使用:-s
(setup)的参数是一个最初要执行的语句,所以你真的只是测试一个空语句.你想做
$ python -m timeit -s "jokes=range(1000000)" "domain=[(0,(len(jokes)*2)-i-1) for i in range(0, len(jokes)*2)]" 10 loops, best of 3: 1.08 sec per loop $ python -m timeit -s "jokes=range(1000000)" "l=len(jokes);domain=[(0,(l*2)-i-1) for i in range(0, l*2)]" 10 loops, best of 3: 908 msec per loop $ python -m timeit -s "jokes=range(1000000)" "l=len(jokes*2);domain=[(0,l-i-1) for i in range(0, l)]" 10 loops, best of 3: 813 msec per loop
虽然加速仍不显着,但更为显着(分别为16%和25%).因此,由于它不会使代码变得更复杂,所以这种简单的优化可能是值得的.
为了解决实际问题...... Python中通常的经验法则是
在编码时优于直接且可读的代码而不是优化.
描述您的代码(profile / cProfile
并且pstats
是您的朋友)以找出您需要优化的内容(通常是紧密循环之类的东西).
作为最后的手段,重新实现这些作为C扩展,使用pyrex和cython等工具可以更轻松.
需要注意的一点是:与许多其他语言相比,函数调用在Python中相对昂贵,这就是为什么示例中的优化会产生差异,即使len
列表的O(1)也是如此.