我多次被告知Python列表推导优于嵌套for
,if
,因为它们被转换为纯C并进行编译。但是,我找不到任何支持此文件的文件;这是真的吗?
例如;以下代码实际上会导致1/3的性能提升(在我的机器上):
import time
start = time.time()
a = []
for i in range(0, 100000000):
a.append(i)
end = time.time()
print("Time it took: " + str((end - start)))
start = time.time()
b = [i for i in range(0, 100000000)]
end = time.time()
print("Time it took: " + str((end - start)))
CPython结果:
Time it took: 12.077988863
Time it took: 8.65817594528
PyPy结果:
Time it took: 4.9356508255
Time it took: 0.686870098114
答案 0 :(得分:2)
这是特定于实现的,但在CPython中,它不是编译为C,而是编译为所谓的“字节码”。
我们可以使用dis
模块检查它,该模块用于反汇编字节码。
>>> import dis
>>> def foo():
... return [i//2 for i in range(20)]
...
>>> dis.dis(foo)
2 0 BUILD_LIST 0
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (20)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 16 (to 32)
16 STORE_FAST 0 (i)
19 LOAD_FAST 0 (i)
22 LOAD_CONST 2 (2)
25 BINARY_FLOOR_DIVIDE
26 LIST_APPEND 2
29 JUMP_ABSOLUTE 13
>> 32 RETURN_VALUE
在其他实现中,它可以编译为C.我对其他实现不太熟悉,所以我会对它们进行评论。
关于你的陈述:
列表推导优于嵌套,如果......
在某些情况下,使用for列表和条件更有意义。最好的方法是使用最易读的内容,然后在需要提高性能时分析代码。有时您实际上并不需要列表推导或生成器表达式创建的列表或生成器,在这种情况下,使用带有if条件的for循环通常更具性能。
但是,在您给出的示例中,您特意打算创建一个列表。在循环中追加到列表是规范的方法,但正如您从检查运行时所知,列表理解更快。它更快的原因是因为Python的设计者知道列表理解将填充列表,因此有机会对其进行优化。在for循环中,优化它会更加困难,因为你必须能够在那里处理更复杂的语句。
我认为你对PyPy的巨大改进是由于优化可以优化i for i part,也许只是在你的迭代器上调用list
。