python - Python 首选语法背后的基本原理

标签 python performance

提倡在 Python 中使用 for i in xrange(...) 样式循环结构背后的基本原理是什么?对于简单的整数循环,开销的差异很大。我使用两段代码进行了一个简单的测试:

文件idiomatic.py:

#!/usr/bin/env python

M = 10000
N = 10000

if __name__ == "__main__":
    x, y = 0, 0
    for x in xrange(N):
        for y in xrange(M):
            pass

文件cstyle.py:

#!/usr/bin/env python

M = 10000
N = 10000

if __name__ == "__main__":
    x, y = 0, 0
    while x < N:
        while y < M:
            y += 1
        x += 1

分析结果如下:

bash-3.1$ time python cstyle.py

real    0m0.109s
user    0m0.015s
sys     0m0.000s

bash-3.1$ time python idiomatic.py

real    0m4.492s
user    0m0.000s
sys     0m0.031s

我能理解为什么 Pythonic 版本较慢——我想这与调用 xrange N 次有很大关系,如果有一种方法可以倒带生成器,也许可以消除这种情况。然而,鉴于执行时间的这种差异,为什么人们更喜欢使用 Pythonic 版本?

编辑:我再次使用Martelli先生提供的代码进行了测试,现在的结果确实更好了:

我想我会在这里列举线程的结论:

1) 模块范围内的大量代码是个坏主意,即使代码包含在 if __name__ == "__main__": block 中也是如此。

2) *奇怪的是,将属于 thebadone 的代码修改为我不正确的版本(让 y 在不重置的情况下增长)在性能上几乎没有差异,即使 M 和 N 的值较大也是如此。

最佳答案

这是正确的比较,例如在 loop.py 中:

M = 10000
N = 10000

def thegoodone():
   for x in xrange(N):
       for y in xrange(M):
           pass

def thebadone():
    x = 0
    while x < N:
        y = 0
        while y < M:
            y += 1
        x += 1

所有实质性代码都应该始终在函数中——在模块的顶层放置一亿个循环显示了对性能的鲁莽漠视,并且 mock 了任何测量 表示性能。

完成后,您会看到:

$ python -mtimeit -s'import loop' 'loop.thegoodone()'
10 loops, best of 3: 3.45 sec per loop
$ python -mtimeit -s'import loop' 'loop.thebadone()'
10 loops, best of 3: 10.6 sec per loop

所以,正确衡量,你提倡的坏方法比Python提倡的好方法慢3倍左右。我希望这能让您重新考虑您的错误主张。

关于python - Python 首选语法背后的基本原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2611867/

相关文章:

python - 从 python 脚本并行运行 bash 脚本

python - 如何优化 100000 次迭代的 python 循环?

python - 在 plumbum 上使用 python 运行 sudo 命令时出现问题

performance - 现代CPU保持标志更新是否需要花费大量资源?

python - 列和行范围内的 Numpy 数组操作

python - 由几张Python Turtle图片组成的电影

python - 将 tfrecords 中的原始字节解码为 tf.feature_column.numeric_column 特征

objective-c - 有人可以帮我改进我的代码,让它运行得更快吗?

android - systrace:HTML 输出的跟踪结果格式无效

java - 优化java循环内的空检查?