Python列表理解是否在每次迭代时追加?

Python列表理解是否在每次迭代时追加?,python,python-3.x,list,Python,Python 3.x,List,我试图理解Python中列表理解的性能,以及使用它们与使用循环创建列表的权衡。使用for循环将元素追加到列表中的已知性能代价之一是,在每次迭代时,它是O(k)(其中k是列表的长度),因为追加需要到达列表的末尾以添加额外的元素 这对于列表理解是如何工作的?在每次迭代中,是否需要到达新列表的末尾以附加新元素 # For loop: # O(n*k) (k=number of elements currently in list) time complexity: new_list = [] for

我试图理解Python中列表理解的性能,以及使用它们与使用循环创建列表的权衡。使用for循环将元素追加到列表中的已知性能代价之一是,在每次迭代时,它是O(k)(其中k是列表的长度),因为追加需要到达列表的末尾以添加额外的元素

这对于列表理解是如何工作的?在每次迭代中,是否需要到达新列表的末尾以附加新元素

# For loop:
# O(n*k) (k=number of elements currently in list) time complexity:
new_list = []
for i in range(n): # O(n)
  new_list.append(i) # O(k) 

# List comprehension:
new_list = [i for i in range(n)] # Is this O(n)? 
我搜索了Python文档、Stack Overflow和其他网站,找不到任何相关信息。关于列表理解的更高层次的信息,有很多参考资料,但没有这样具体的内容

如果您不能提供答案,请告诉我,或者告诉我如何查看实际的底层Python列表理解代码,这样我就可以自己完成这项工作了?

添加到列表中是分期付款的
O(1)
而不是
O(k)
;列表实现为可变长度数组,而不是链表。复杂性既适用于
循环,也适用于
my_list.append的
调用和列表理解(其中,扰流板警报也适用于append)

所以在这两种情况下。复杂性是
O(N)

列表理解通常表现得更好,因为它们专门做一件事:创建列表。为它们生成的字节码特定于此。(参见字节码)

还要注意,列表理解,如循环,不一定在每次迭代时追加。通常使用
if
子句过滤掉正在循环的iterable的元素


如果您想了解列表理解是如何在CPython中实现的,您可以查看为它们生成的字节码,并通过
ceval.c
扫描每个字节执行的操作

编译列表理解表达式后,可以使用dis查看字节码:

dis(compile('[i for i in range(10)]', '', 'exec').co_consts[0])
  1           0 BUILD_LIST               0
              2 LOAD_FAST                0 (.0)
        >>    4 FOR_ITER                 8 (to 14)
              6 STORE_FAST               1 (i)
              8 LOAD_FAST                1 (i)
             10 LIST_APPEND              2
             12 JUMP_ABSOLUTE            4
        >>   14 RETURN_VALUE
然后,或者在中查看他们的文档

附加到列表中的是摊销的
O(1)
,而不是
O(k)
;列表实现为可变长度数组,而不是链表。复杂性既适用于
循环,也适用于
my_list.append的
调用和列表理解(其中,扰流板警报也适用于append)

所以在这两种情况下。复杂性是
O(N)

列表理解通常表现得更好,因为它们专门做一件事:创建列表。为它们生成的字节码特定于此。(参见字节码)

还要注意,列表理解,如循环,不一定在每次迭代时追加。通常使用
if
子句过滤掉正在循环的iterable的元素


如果您想了解列表理解是如何在CPython中实现的,您可以查看为它们生成的字节码,并通过
ceval.c
扫描每个字节执行的操作

编译列表理解表达式后,可以使用dis查看字节码:

dis(compile('[i for i in range(10)]', '', 'exec').co_consts[0])
  1           0 BUILD_LIST               0
              2 LOAD_FAST                0 (.0)
        >>    4 FOR_ITER                 8 (to 14)
              6 STORE_FAST               1 (i)
              8 LOAD_FAST                1 (i)
             10 LIST_APPEND              2
             12 JUMP_ABSOLUTE            4
        >>   14 RETURN_VALUE

然后,或者在中查看他们的文档

new\u list.append(i)
不是
O(k)
。插入可能是错误的。但是它们被优化为使用
append
检查源代码?为了提高性能,您可以使用
%timeit
magic运算符。“列表理解比循环的等效运算速度快一点(除非您只是想扔掉结果)。”from:
new\u List.append(i)
不是
O(k)
。插入可能是错误的。但是它们被优化为使用
append
检查源代码?为了提高性能,您可以使用
%timeit
魔术运算符。“列表理解比循环的等效运算速度快一点(除非您刚刚要放弃结果)。”发件人:可能值得一提的是,为了完整性,您也可以在列表理解中嵌套循环,但答案很棒!可能值得一提的是,为了完整性,您还可以在列表中嵌套for循环,但答案很棒!