为什么列表理解比附加列表要快得多?

我想知道为什么列表理解比附加到列表要快得多。我以为差异只是表达性的,不是。


>>> import timeit 

>>> timeit.timeit(stmt='''\

t = []

for i in range(10000):

    t.append(i)''', number=10000)

9.467898777974142


>>> timeit.timeit(stmt='t= [i for i in range(10000)]', number=10000)

4.1138417314859

列表理解速度提高了50%。为什么?


RISEBY
浏览 273回答 3
3回答

ITMISS

列表理解基本上只是常规for循环的“语法糖” 。在这种情况下,它执行得更好的原因是因为它不需要加载列表的append属性并在每次迭代时都将其作为函数调用。换句话说,一般而言,列表理解的执行速度更快,因为挂起和恢复一个函数的框架(在其他情况下是多个函数)要比按需创建列表慢。考虑以下示例:# Python-3.6In [1]: import disIn [2]: def f1():&nbsp; &nbsp;...:&nbsp; &nbsp; &nbsp;l = []&nbsp; &nbsp;...:&nbsp; &nbsp; &nbsp;for i in range(5):&nbsp; &nbsp;...:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;l.append(i)&nbsp; &nbsp;...:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;In [3]: def f2():&nbsp; &nbsp;...:&nbsp; &nbsp; &nbsp;[i for i in range(5)]&nbsp; &nbsp;...:&nbsp; &nbsp; &nbsp;In [4]: dis.dis(f1)&nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 BUILD_LIST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 STORE_FAST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 (l)&nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;6 SETUP_LOOP&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 33 (to 42)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 LOAD_GLOBAL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 (range)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 (5)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;15 CALL_FUNCTION&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 (1 positional, 0 keyword pair)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;18 GET_ITER&nbsp; &nbsp; &nbsp; &nbsp; >>&nbsp; &nbsp;19 FOR_ITER&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 19 (to 41)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;22 STORE_FAST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 (i)&nbsp; 4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 25 LOAD_FAST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 (l)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;28 LOAD_ATTR&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 (append)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;31 LOAD_FAST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 (i)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;34 CALL_FUNCTION&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 (1 positional, 0 keyword pair)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;37 POP_TOP&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;38 JUMP_ABSOLUTE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;19&nbsp; &nbsp; &nbsp; &nbsp; >>&nbsp; &nbsp;41 POP_BLOCK&nbsp; &nbsp; &nbsp; &nbsp; >>&nbsp; &nbsp;42 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 (None)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;45 RETURN_VALUEIn [5]: dis.dis(f2)&nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 (<code object <listcomp> at 0x7fe48b2265d0, file "<ipython-input-3-9bc091d521d5>", line 2>)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 ('f2.<locals>.<listcomp>')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 MAKE_FUNCTION&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 LOAD_GLOBAL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 (range)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3 (5)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;15 CALL_FUNCTION&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 (1 positional, 0 keyword pair)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;18 GET_ITER&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;19 CALL_FUNCTION&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 (1 positional, 0 keyword pair)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;22 POP_TOP&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;23 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 (None)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;26 RETURN_VALUE您可以在偏移量22处看到我们append在第一个函数中有一个属性,因为使用列表推导在第二个函数中没有这样的东西。所有这些额外的字节码将使附加方法变慢。还要注意,append在每次迭代中还将加载属性,这会使您的代码比使用列表理解的第二个函数慢大约2倍的时间。

四季花海

援引该文章,那是因为append的属性list没有抬头,加载并作为函数调用,这需要时间,并且在迭代加起来。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python