为什么是列表.追加(x) 比list+=l[x]更有效?

2024-04-26 21:29:03 发布

您现在位置:Python中文网/ 问答频道 /正文

可以通过两种方式添加到列表:

(一)

mat = []
for i in range(10):
    mat.append(i)

或者

(二)

^{pr2}$

official Python documentation

The method append() shown in the example is defined for list objects; it adds a new element at the end of the list. In this example it is equivalent to result = result + [a], but more efficient.

文件表明,方法1更有效。为什么会这样?在


Tags: thein列表forisexample方式range
3条回答


import timeit
timeit.timeit('for i in range(10): mat.append(i)', 'mat = []')
1.798893928527832
timeit.timeit('for i in range(10): mat += [i]', 'mat = []')
2.547478199005127

方法append更快,因为它不使用任何类型转换。在

尽管使用.append需要一个方法调用,但它实际上比使用增广赋值运算符+=略为有效。在

但是使用.append还有一个更好的理由:当要附加到的列表不在本地范围内时,可以这样做,因为它只是在外部范围内调用一个对象的方法,而不能对不在本地范围内的对象执行赋值,除非将它们声明为全局(或非本地),通常最好避免的做法。在

下面是一个例子:

mat = []

def test_append():
    for i in range(10):
        #mat += [i]
        mat.append(i)

def test_iadd():
    for i in range(10):
        mat += [i]

test_append()
print(mat)
test_iadd()
print(mat)

输出

^{pr2}$

当然,我们可以将mat作为参数传递给函数:

mat = []

def test_append():
    for i in range(10):
        #mat += [i]
        mat.append(i)

def test_iadd2(mat):
    for i in range(10):
        mat += [i]

test_append()
print(mat)
test_iadd2(mat)
print(mat)

输出

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

^{较慢的一个原因是它必须在每个循环上构造一个新的[i]列表。在

FWIW,字节码如下:

test_append
 21           0 SETUP_LOOP              33 (to 36)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (10)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                19 (to 35)
             16 STORE_FAST               0 (i)

 23          19 LOAD_GLOBAL              1 (mat)
             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        

test_iadd2
 26           0 SETUP_LOOP              33 (to 36)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (10)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                19 (to 35)
             16 STORE_FAST               1 (i)

 27          19 LOAD_FAST                0 (mat)
             22 LOAD_FAST                1 (i)
             25 BUILD_LIST               1
             28 INPLACE_ADD         
             29 STORE_FAST               0 (mat)
             32 JUMP_ABSOLUTE           13
        >>   35 POP_BLOCK           
        >>   36 LOAD_CONST               0 (None)
             39 RETURN_VALUE        

上面的字节码转储是使用dis模块生成的:

from dis import dis

mat = []

def test_append():
    for i in range(10):
        #mat += [i]
        mat.append(i)

def test_iadd2(mat):
    for i in range(10):
        mat += [i]

print('test_append')
dis(test_append)

print('\ntest_iadd2')
dis(test_iadd2)

第二个比较慢,因为它创建了一个新列表(这有点慢)。在

相关问题 更多 >