2013-06-03 75 views
3

为什么列表理解有更好的性能比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结构性能差?

+2

*是否有其他示例(非循环),当一个Python结构比其他Python结构的性能差?* - 无限多。 –

+0

@Lattyware,例如? –

+5

如果性能是唯一的原因,你不应该太担心lc vs loop。担心你的整体算法是健全的,并担心你可以理解你编写的代码。 – dawg

回答

8

从本质上讲,列表理解和循环做的事情非常相似,列表理解消除了一些开销并使其看起来很漂亮。 要理解为什么这是更快,你应该看看在Efficiency of list comprehensions和引用有关问题的相关部分:

列表理解这里更好地发挥,因为你不需要加载 追加属性关闭名单(循环程序,字节码28)和 称之为函数(循环程序,字节码38)。相反,在 的理解中,为快速附加到结果列表(理解程序,字节码33)上的 生成专用的LIST_APPEND字节码。

在loop_faster程序,你避免追加 属性查找的开销提升它的循环,并把结果 在fastlocal(字节码9-12),所以它更快速地循环;然而, 理解使用专门的LIST_APPEND字节码而不是 招致函数调用的开销,所以它仍然胜过。

该链接还详细介绍了与lc相关的一些可能的缺陷,我建议您通过一次。

+0

如果你想要时间你的代码,你可以使用''%timeit' 'ipython中的神奇功能 – goofd

+0

LC不需要担心语句之类的事情,因为LC中只允许表达式。 –

+0

这不太好。这是非常长的声明,所以我必须将其分成多行。一旦出现这种情况,理解对我来说就没什么意义了:'[[如果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

1

the python wiki

for语句是最常用的。它遍历 一个序列的元素,将每个元素分配给循环变量。如果 循环的主体很简单,那么for循环的解释器开销本身可能是大量的开销。这是地图功能 方便的地方。你可以把map看作一个移动到C代码的地方。

如此简单的循环有列表解析带来的开销。

3

假设我们在这里谈论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循环使用。

相关问题