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