Python首选for语法的原因

11 投票
5 回答
537 浏览
提问于 2025-04-15 21:26

为什么在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

我能理解为什么Python的写法会更慢——我想这和调用xrange N次有很大关系,或许如果有办法重置生成器,这个问题就能解决。不过,考虑到执行时间差别这么大,为什么还会有人选择使用Python的写法呢?

补充:我再次使用Mr. Martelli提供的代码进行了测试,结果确实有所改善:

我想在这里总结一下这个讨论的结论:

1) 在模块级别写很多代码是个坏主意,即使这些代码被放在if __name__ == "__main__":这个块里。

2) *有趣的是,把thebadone的代码改成我错误的版本(让y增长而不重置)对性能几乎没有影响,即使在M和N的值很大时也是如此。

5 个回答

3

适合遍历数据结构

for i in ... 这种写法非常适合用来遍历数据结构。在一些底层语言中,你通常需要通过一个整数来索引数组,但在Python中,这种写法让你可以省去索引的步骤。

11

你在内层循环结束后忘记把y重置为0了。

#!/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
        y = 0

修复后运行时间是20.63秒,而使用xrange时是6.97秒。

22

这里是正确的比较,比如在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

所有重要的代码应该总是放在函数里——在模块的最顶层放一亿个循环,这样做完全不考虑性能,也让任何尝试去测量性能的努力变得毫无意义。

一旦你这样做了,你会看到:

$ 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倍。我希望这能让你重新考虑你错误的观点。

撰写回答