让我们定义回答问题并为其计时所需的功能:
In [18]: def iter(): l = [x for x in range(100) if x > 10] ....:In [19]: %timeit iter()100000 loops, best of 3: 7.92 µs per loopIn [20]: def loop(): l = [] for x in range(100): if x > 10: l.append(x) ....:In [21]: %timeit loop()10000 loops, best of 3: 20 µs per loopIn [22]: def loop_fast(): l = [] for x in range(100): if x > 10: pass ....:In [23]: %timeit loop_fast()100000 loops, best of 3: 4.69 µs per loop
我们可以看到,没有append命令的for循环与列表理解一样快。实际上,如果我们看一下字节码,就会发现在列表理解的情况下,python能够使用名为LIST_APPEND的内置字节码命令来代替:
- 加载列表:40 LOAD_FAST
- 加载属性:43 LOAD_ATTRIBUTE
- 调用已加载的函数:49 CALL_FUNCTION
- 卸载列表(?):52 POP_TOP
从输出下面可以看到,列表理解和“ loop_fast”函数缺少前一个字节码。比较这三个函数的时间很明显,它们负责三种方法的不同时序。
In [27]: dis.dis(iter) 2 0 BUILD_LIST 0 3 LOAD_GLOBAL 0 (range) 6 LOAD_ConST 1 (1) 9 LOAD_ConST 2 (100) 12 CALL_FUNCTION 2 15 GET_ITER >> 16 FOR_ITER 24 (to 43) 19 STORE_FAST 0 (x) 22 LOAD_FAST 0 (x) 25 LOAD_ConST 2 (100) 28 COMPARE_OP 4 (>) 31 POP_JUMP_IF_FALSE 16 34 LOAD_FAST 0 (x) 37 LIST_APPEND 2 40 JUMP_ABSOLUTE 16 >> 43 STORE_FAST 1 (l) 46 LOAD_ConST 0 (None) 49 RETURN_VALUEIn [28]: dis.dis(loop) 2 0 BUILD_LIST 0 3 STORE_FAST 0 (1) 3 6 SETUP_LOOP 51 (to 60) 9 LOAD_GLOBAL 0 (range) 12 LOAD_ConST 1 (1) 15 LOAD_ConST 2 (100) 18 CALL_FUNCTION 2 21 GET_ITER >> 22 FOR_ITER 34 (to 59) 25 STORE_FAST 1 (x) 4 28 LOAD_FAST 1 (x) 31 LOAD_ConST 3 (10) 34 COMPARE_OP 4 (>) 37 POP_JUMP_IF_FALSE 22 5 40 LOAD_FAST 0 (l) 43 LOAD_ATTR 1 (append) 46 LOAD_FAST 1 (x) 49 CALL_FUNCTION 1 52 POP_TOP 53 JUMP_ABSOLUTE 22 56 JUMP_ABSOLUTE 22 >> 59 POP_BLOCK >> 60 LOAD_ConST 0 (None) 63 RETURN_VALUEIn [29]: dis.dis(loop_fast) 2 0 BUILD_LIST 0 3 STORE_FAST 0 (1) 3 6 SETUP_LOOP 38 (to 47) 9 LOAD_GLOBAL 0 (range) 12 LOAD_ConST 1 (1) 15 LOAD_ConST 2 (100) 18 CALL_FUNCTION 2 21 GET_ITER >> 22 FOR_ITER 21 (to 46) 25 STORE_FAST 1 (x) 4 28 LOAD_FAST 1 (x) 31 LOAD_ConST 3 (10) 34 COMPARE_OP 4 (>) 37 POP_JUMP_IF_FALSE 22 5 40 JUMP_ABSOLUTE 22 43 JUMP_ABSOLUTE 22 >> 46 POP_BLOCK >> 47 LOAD_ConST 0 (None) 50 RETURN_VALUE



