为什么在循环范围()在Python比使用while循环更快?

有一天我正在做一些Python基准testing,并且遇到了一些有趣的事情。 下面是两个或多或less做同样的事情循环。 循环1需要循环2的两倍左右才能执行。

循环1:

int i = 0 while i < 100000000: i += 1 

循环2:

 for n in range(0,100000000): pass 

为什么第一个循环这么慢? 我知道这是一个微不足道的例子,但这引起了我的兴趣。 range()函数有什么特别之处,它比以同样的方式递增variables更有效率?

看到反汇编python字节码,你可能会得到更具体的想法

使用while循环:

 1 0 LOAD_CONST 0 (0) 3 STORE_NAME 0 (i) 2 6 SETUP_LOOP 28 (to 37) >> 9 LOAD_NAME 0 (i) # <- 12 LOAD_CONST 1 (100000000) # <- 15 COMPARE_OP 0 (<) # <- 18 JUMP_IF_FALSE 14 (to 35) # <- 21 POP_TOP # <- 3 22 LOAD_NAME 0 (i) # <- 25 LOAD_CONST 2 (1) # <- 28 INPLACE_ADD # <- 29 STORE_NAME 0 (i) # <- 32 JUMP_ABSOLUTE 9 # <- >> 35 POP_TOP 36 POP_BLOCK 

循环体有10个操作

使用范围:

 1 0 SETUP_LOOP 23 (to 26) 3 LOAD_NAME 0 (range) 6 LOAD_CONST 0 (0) 9 LOAD_CONST 1 (100000000) 12 CALL_FUNCTION 2 15 GET_ITER >> 16 FOR_ITER 6 (to 25) # <- 19 STORE_NAME 1 (n) # <- 2 22 JUMP_ABSOLUTE 16 # <- >> 25 POP_BLOCK >> 26 LOAD_CONST 2 (None) 29 RETURN_VALUE 

循环体有3个操作

运行C代码的时间比intepretor短得多,可以忽略。

range()在C中实现,而i += 1被解释。

使用xrange()可以使大数更快。 从Python 3.0开始, range()与以前的xrange()相同。

必须说的是,while循环中有很多对象的创build和破坏。

 i += 1 

是相同的:

 i = i + 1 

但是由于Python ints是不可变的,它不会修改现有的对象; 而是创造一个全新的具有新价值的对象。 这基本上是:

 i = new int(i + 1) # Using C++ or Java-ish syntax 

垃圾收集器也将有大量的清理工作。 “对象创造是昂贵的”。

因为在解释器中用C编写的代码更经常运行。 即i + = 1是在Python中,所以慢(比较),而范围(0,…)是一个C调用,for循环将主要在C中执行。

Python内build的大部分方法调用都是以C代码的forms运行的。 必须解释的代码要慢得多。 在内存效率和执行速度方面,差异是巨大的。 python内部已经被优化到极致,最好利用这些优化。