繁体   English   中英

Python列表推导是否在每次迭代时附加?

[英]Do Python list comprehensions append at each iteration?

我试图了解Python中列表理解的性能,以及使用它们与for循环创建列表的权衡。 使用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) 列表被实现为可变长度数组,而不是链接列表。 复杂性既适用for使用my_list.append调用的for循环,也适用于列表理解(后者,扰流器警报, 还可以追加)。

因此,在两种情况下。 复杂度为O(N)

列表综合通常表现更好,因为它们专门做一件事: 创建列表 为它们生成的字节码是特定于此的。 (请参阅LIST_APPEND字节码)

还要注意,列表理解,例如for循环,不一定在每次迭代时都附加。 通常使用if子句过滤掉要遍历的可迭代元素。


如果您想了解如何在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

然后, 浏览ceval.c的案例,或在dis模块中查看其文档。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM