为什么列表理解有更好的性能比for循环,在Python中?Python List Comprehension vs
列表理解:
new_items = [a for a in items if a > 10]
for循环:
new_items = []
for a in items:
if a > 10: new_items.append(a)
是否还有其他的例子(不循环),其中一个Python的结构具有比另一个Python结构性能差?
为什么列表理解有更好的性能比for循环,在Python中?Python List Comprehension vs
列表理解:
new_items = [a for a in items if a > 10]
for循环:
new_items = []
for a in items:
if a > 10: new_items.append(a)
是否还有其他的例子(不循环),其中一个Python的结构具有比另一个Python结构性能差?
从本质上讲,列表理解和循环做的事情非常相似,列表理解消除了一些开销并使其看起来很漂亮。 要理解为什么这是更快,你应该看看在Efficiency of list comprehensions和引用有关问题的相关部分:
列表理解这里更好地发挥,因为你不需要加载 追加属性关闭名单(循环程序,字节码28)和 称之为函数(循环程序,字节码38)。相反,在 的理解中,为快速附加到结果列表(理解程序,字节码33)上的 生成专用的LIST_APPEND字节码。
在loop_faster程序,你避免追加 属性查找的开销提升它的循环,并把结果 在fastlocal(字节码9-12),所以它更快速地循环;然而, 理解使用专门的LIST_APPEND字节码而不是 招致函数调用的开销,所以它仍然胜过。
该链接还详细介绍了与lc相关的一些可能的缺陷,我建议您通过一次。
如果你想要时间你的代码,你可以使用''%timeit' 'ipython中的神奇功能 – goofd
LC不需要担心语句之类的事情,因为LC中只允许表达式。 –
这不太好。这是非常长的声明,所以我必须将其分成多行。一旦出现这种情况,理解对我来说就没什么意义了:'[[如果item_idx == row_idx其他0为范围(0,3)中的item_idx]]为范围(0,3)]中的row_idx] https://python-3-patterns-idioms-test.readthedocs.org/en/latest/Comprehensions.html。 – Schultz9999
for语句是最常用的。它遍历 一个序列的元素,将每个元素分配给循环变量。如果 循环的主体很简单,那么for循环的解释器开销本身可能是大量的开销。这是地图功能 方便的地方。你可以把map看作一个移动到C代码的地方。
如此简单的循环有列表解析带来的开销。
假设我们在这里谈论CPython中,您可以使用dis
模块比较生成的字节码:
>> def one():
return [a for a in items if a > 10]
>> def two():
res = []
for a in items:
if a > 10:
res.append(a)
>> dis.dis(one)
2 0 BUILD_LIST 0
3 LOAD_GLOBAL 0 (items)
6 GET_ITER
>> 7 FOR_ITER 24 (to 34)
10 STORE_FAST 0 (a)
13 LOAD_FAST 0 (a)
16 LOAD_CONST 1 (10)
19 COMPARE_OP 4 (>)
22 POP_JUMP_IF_FALSE 7
25 LOAD_FAST 0 (a)
28 LIST_APPEND 2
31 JUMP_ABSOLUTE 7
>> 34 RETURN_VALUE
>> dis.dis(two)
2 0 BUILD_LIST 0
3 STORE_FAST 0 (res)
3 6 SETUP_LOOP 42 (to 51)
9 LOAD_GLOBAL 0 (items)
12 GET_ITER
>> 13 FOR_ITER 34 (to 50)
16 STORE_FAST 1 (a)
4 19 LOAD_FAST 1 (a)
22 LOAD_CONST 1 (10)
25 COMPARE_OP 4 (>)
28 POP_JUMP_IF_FALSE 13
5 31 LOAD_FAST 0 (res)
34 LOAD_ATTR 1 (append)
37 LOAD_FAST 1 (a)
40 CALL_FUNCTION 1
43 POP_TOP
44 JUMP_ABSOLUTE 13
47 JUMP_ABSOLUTE 13
>> 50 POP_BLOCK
>> 51 LOAD_CONST 0 (None)
54 RETURN_VALUE
因此,对于一两件事,列表解析需要专用LIST_APPEND
操作码这是不的优势被for循环使用。
*是否有其他示例(非循环),当一个Python结构比其他Python结构的性能差?* - 无限多。 –
@Lattyware,例如? –
如果性能是唯一的原因,你不应该太担心lc vs loop。担心你的整体算法是健全的,并担心你可以理解你编写的代码。 – dawg