我多次被告知 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
最佳答案
这是特定于实现的,但在 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。我对这些其他实现不太熟悉,因此我将保留对它们的评论。
关于您的声明:
list comprehensions are better than nested for, if ...
在某些情况下,使用 for 列表和条件更有意义。最好的方法是使用您最易读的内容,然后在需要提高性能时分析您的代码。有时,您实际上并不需要由列表理解或生成器表达式创建的列表或生成器,在这种情况下,使用带有 if 条件的 for 循环通常性能更高。
推测:
但是,在您给出的示例中,您特别打算创建一个列表。在循环中附加到列表是执行此操作的规范方法,但正如您通过检查运行时知道的那样,列表理解速度更快。它更快的原因是 Python 的设计者知道列表推导将填充列表,因此有机会对其进行优化。在 for 循环中,优化它会更加困难,因为您必须能够在那里处理更复杂的语句。
我想您在 PyPy 中的巨大改进是由于对 i for i 部分进行了优化,并且可能只是在迭代器上调用 list
。
关于python - python 列表推导式是否会转换为纯 C 语言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24482810/