Why is list comprehension so faster?

This question already has an answer here:

  • Python list comprehension expensive 1 answer

  • List comprehensions perform better here because you don't need to load the append attribute of the list and call it as a function!*

    Consider the following example :

    >>> import dis
    >>> def f1():
    ...   for i in range(5):
    ...      l.append(i)
    ... 
    >>> def f2():
    ...   [i for i in range(5)]
    ... 
    >>> dis.dis(f1)
      2           0 SETUP_LOOP              33 (to 36)
                  3 LOAD_GLOBAL              0 (range)
                  6 LOAD_CONST               1 (5)
                  9 CALL_FUNCTION            1
                 12 GET_ITER            
            >>   13 FOR_ITER                19 (to 35)
                 16 STORE_FAST               0 (i)
    
      3          19 LOAD_GLOBAL              1 (l)
                 22 LOAD_ATTR                2 (append)
                 25 LOAD_FAST                0 (i)
                 28 CALL_FUNCTION            1
                 31 POP_TOP             
                 32 JUMP_ABSOLUTE           13
            >>   35 POP_BLOCK           
            >>   36 LOAD_CONST               0 (None)
                 39 RETURN_VALUE        
    >>> dis.dis(f2)
      2           0 BUILD_LIST               0
                  3 LOAD_GLOBAL              0 (range)
                  6 LOAD_CONST               1 (5)
                  9 CALL_FUNCTION            1
                 12 GET_ITER            
            >>   13 FOR_ITER                12 (to 28)
                 16 STORE_FAST               0 (i)
                 19 LOAD_FAST                0 (i)
                 22 LIST_APPEND              2
                 25 JUMP_ABSOLUTE           13
            >>   28 POP_TOP             
                 29 LOAD_CONST               0 (None)
                 32 RETURN_VALUE        
    >>> 
    

    You can see that in byte-code 22 we have an append attribute in first function since we have not such thing in second function using list comprehension.

    Also note that you'll have append attr loading in each iteration thus it makes your code takes approximately 2 time slower than the second function using list comprehension.

    Moreover, depending on your Python and code, list comprehensions might run much faster than manual for loop statements (often roughly twice as fast) because their iterations are performed at C language speed inside the interpreter, rather than with manual Python code. Especially for larger data sets, there is often a major performance advantage to using this expression.**


    *You can read more about Efficiency of list comprehensions

    ** Learning Python by Mark Lutz


    即使不考虑查找和加载append函数所花费的时间,列表理解仍然更快,因为列表是以C语言创建的,而不是一次在Python中构建一个项目。

    # Slow
    timeit.timeit(stmt='''
        for i in range(10000):
            t.append(i)''', setup='t=[]', number=10000)
    
    # Faster
    timeit.timeit(stmt='''
        for i in range(10000):
            l(i)''', setup='t=[]; l=t.append', number=10000)
    
    # Faster still
    timeit.timeit(stmt='t = [i for i in range(10000)]', number=10000)
    

    引用这篇文章,是因为listappend属性没有被查找,加载并作为一个函数被调用,这需要时间并且会叠加迭代。

    链接地址: http://www.djcxy.com/p/69948.html

    上一篇: 在给定条件的情况下增加前n个列表元素

    下一篇: 为什么列表理解如此之快?