質問の背景
リスト(list)は、Pythonにおける基本的な組み込みデータ型のひとつで、言語の初期バージョンから存在します。時が経つにつれ、その内部構造はパフォーマンスやプログラミングの快適さを向上させるために改善されてきました。
問題
Pythonのリストは、連結リストではなく動的配列として実装されていることを理解することが重要です。この誤解は、非効率的なコードや操作の計算の誤りを引き起こします。
解決策
リストは、必要に応じて割り当てられたメモリのサイズを「跳躍的に」増加させる動的配列として実装され、要素の追加時の永続的なコストを回避します。これにより、リストの末尾に要素を挿入または削除する際に、平均してO(1)の時間がかかります。リストの中間や先頭に挿入または削除するには、要素を移動させる必要があり、これはO(n)の時間がかかります。
コード例:
my_list = [1, 2, 3] my_list.append(4) # 末尾に追加 my_list.insert(1, 'a') # インデックスに挿入 print(my_list)
主な特徴:
PythonのリストはC言語の配列に相当すると考えられるか?違いは何か?
いいえ、C言語の配列は固定型の要素を持ち、メモリ上に連続して配置されます。Pythonのリストは、各要素がヒープ内の独立した任意の型のオブジェクトを指すポインタの配列です。
ループの中でリストの先頭に要素を挿入すると何が起こるか?これは速いのか?
いいえ、これは遅いです:先頭(位置0)に挿入すると、毎回既存のすべての要素が右にシフトします。アモチュネーションされた複雑さはO(n)であり、大きなリストではパフォーマンスが悪化します。
リストに対する演算子+とappend/extendの違いは何か?
+は新しいリストを作成し、古いリストは変更しません。appendは、元のリストの末尾に要素を追加します。extendは、もう一つのシーケンスからすべての要素をリストに追加し、元のオブジェクトを変更します。
lst1 = [1, 2] lst2 = [3, 4] lst3 = lst1 + lst2 # lst3は新しいリスト lst1.append(lst2) # lst1は[1, 2, [3, 4]]になる lst1.extend(lst2) # lst1は[1, 2, 3, 4]に変わる、前回のappendの後にlst1をリセットしていなければ
プロジェクトで最初の要素を保持し、常に削除するためにリストを使用しました。大量のデータを扱う際に明らかな遅延に気付きました。
利点:
欠点:
問題を把握した後、リストをcollections.dequeに置き換えました。これはそのような操作に最適化されています。
利点:
欠点: