簡體   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