我在一个入门的comp-sci课程(经过多年的网络编程之后),并且对我用单行程获得的速度感到好奇,如果有的话.
for line in lines: numbers.append(eval(line.strip().split()[0]))
所以我用痛苦的显式作业写了同样的东西,然后互相对抗.
for line in lines: a = line.split() b = a[0] c = b.strip() d = eval(c) numbers.append(d)
第二个运行速度快 30ms (在我的FreeBSD shell帐户上;参见编辑#2),输入文件为100K行!当然这是在3秒的总运行时间,因此百分比并不大...但我真的很惊讶看到所有那些明确命名的任务以某种方式帮助.
有一个最近的线程上的功能,而不是内联代码的性能,但这似乎更基本.是什么赋予了?我是否应该亲切地编写冗长冗长的代码并告诉我的嘲笑同事这是出于性能原因?(值得庆幸的是,列表理解版本运行速度提高了约10ms,因此我所珍视的紧凑性并不完全在窗外.)
编辑:感谢您对我的草率扩展代码的提示.你是对的,第二个应该是真的:
for line in lines: a = line.strip() b = a.split() c = b[0] d = eval(c) numbers.append(d)
然而,即使我已经解决了这个问题,我的时间分别是2.714s,2.652s和2.624s,对于单线程,完全爆炸形式和列表理解(未图示).所以我的问题就是!
编辑#2:有趣的是,即使对于一群知识渊博的人来说答案似乎并不明显,这让我对这个问题感觉好一些!在这种情况和类似的情况下,我现在可能会自己玩一下,看看会发生什么.如果你愿意,一定要继续修补线程,但是我要宣布我收到的答案是"嗯,这很有趣;一定是深刻的东西." 特别是因为steveha指出,机器之间的行为并不一致 - 在我的Debian和Windows安装上,另一个方向略有不同.感谢所有贡献的人!
您的代码未按相同顺序展开.紧凑版本:
A > B > C > D > E
而你的爆炸版本去了
B > C > A > D > E
结果是strip()被推迟2步,这可能会影响性能,具体取决于输入的内容.
坦率地说,第一个版本,一切都在一行,是一个难以阅读.
第二个可能有点过于冗长(中间的东西会被欣赏),但它肯定更好.
由于Python内部原因,我不太关心微优化,只关注可读代码.
顺便说一句:两个(初始)版本没有做同样的事情.
在前者中,首先剥离,然后分割,而在后者中首先分割然后剥离(此外,只有第一个元素).
同样,我认为你忽略了这一点,因为以前的版本很难关注.
然后,使用dis
(python反汇编程序)分析这两个(更新的)版本,显示两个代码之间没有真正的区别,只显示了如何查找函数名称的顺序.这可能会对性能产生影响.
虽然我们正在讨论这个问题,但只需在循环之前将eval绑定到局部变量,就可以获得一些性能提升.我希望在这个改变之后,两个版本之间的时间应该没有差别.
例如:
eval_ = eval for line in lines: a = line.strip() b = a.split() c = b[0] d = eval_(c) numbers.append(d)
我们主要讨论的是微优化,但这种混叠实际上是一种在某些情况下可能非常有用的技术.