Skip to content
This page has been auto-translated and may contain errors.View in English

リスト

docs.scrimba.com

変数は1つのものを保持します。リストは多くのものを順序付けして保持し、すべて1つの名前の下にあります。リーダーボードはスコアの順位付きシーケンスです。クイズは質問の集合です。関連する値のグループを管理する必要が出てくると、リストが必要になります。

リストはPythonの汎用順序付き可変シーケンスです。時間とともに変わるもの、つまり追加または削除されるアイテム、順序がシャッフルされるアイテム、内容がフィルタリングまたはソートされるものに最適です。順序が重要で、コレクションが変わる場合、リストが通常は最初の選択です。

listはPythonの動的配列:順序付けされた可変(変更可能)シーケンスです。パフォーマンスプロファイルが設計上の決定を推進します。インデックスによる読み取りはO(1)で、リストの大きさに関わらず常時時間です(big-Oはコストがサイズnに応じてどのようにスケーリングするかの略語)。append()も実質的にはO(1)です:リストは末尾に予備スペースを保持し、時々だけサイズ変更されます。コストがかかるのはinsert()remove()でO(n)です。変更点の後のすべての要素がシフトするためです。フロントに繰り返し追加または削除している場合、そのO(n)がシグナルになり、別の構造を探します。

リストの作成

角括弧、カンマで区切られた値。リストはあらゆる種類の混合を保持できますし、空のリストは有効で、時間をかけて構築する開始点として一般的です。

リストはブラケット構文で定義され、挿入順序を保持します。あらゆるPython値を保持できます(他のリストを含む)。空のリスト[]は、アイテムを段階的に蓄積するときの標準的な開始点です。

ブラケットリテラルは新しいlistオブジェクトを作成し、リストは要素への参照を保持します。値をコピーするのではなく(参照は実際のオブジェクトが存在する場所へのポインタです)。したがって、要素は別のリストを含むあらゆるPythonオブジェクトでも可能です。1つのリストで型を混ぜることは有効ですが、簡単なスクリプトの外では一般的ではありません:一般的に保持しておくリストは1つの型を保持し、それらについて推論しやすく、ループで処理しやすくなります。

python
scores = [87, 92, 74, 65, 91]
players = ["太郎", "花子", "次郎"]
mixed = ["太郎", 87, True, 3.14]   # 任意の型、ただし一般的ではない
empty = []
Junoリストの作成 角括弧内の値、カンマで区切られた値を使用します。Pythonはあなたが書いた順序でそれらを保持します。空の[]は、あなたが行く際にそれを埋める計画があるときの良い開始点です。私のほとんどのリストはそのように開始します。空で待機中です。
Junoリストの作成 括弧がリストを定義し、挿入順序が保持されます。リストはあらゆる値(他のリストを含む)を保持できます。また[]は、アイテムを段階的に蓄積するときの標準的な開始方法です。
Junoリストの作成 リストはその要素への参照を保持しているため、あらゆるオブジェクトを混ぜることができますが、実際に保持したいものはリスト1つあたり1つの型です。[]を使用して構築し、過剰割り当てがそれを安くします。

インデックス処理とスライシング

リストは文字列と同じ番号付けを使用します:位置は0から始まり、負の数は末尾から数えます。位置によってあらゆるアイテムを読み取ります。リストは可変性があるため、特定の位置に書き込むこともできます。

リストのインデックス処理とスライシングは、文字列と同じ規則に従います。重要な違いは可変性:インデックスまたはスライスに割り当てて、アイテムを変更します。これは文字列が許可していないものです。

インデックス処理とスライシング読み取りはstringと同じですが、リストは可変性があるため、割り当てることができます。認識する必要のあるものはスライス割り当てです。リストの長さを変更します。lst[1:3] = [10, 20, 30]は位置1および2の2つのアイテムを3つの新しいアイテムに置き換え、リストを1つ拡張します。置き換えはスライスの長さと一致する必要がないため、便利で一般的な驚きです。意図的に到達してください。事故ではなく。

python
scores = [87, 92, 74, 65, 91]

scores[0]      # 87  (最初)
scores[-1]     # 91  (最後)
scores[1:3]    # [92, 74]
scores[:2]     # [87, 92]
scores[::-1]   # [91, 65, 74, 92, 87]  (逆順)

scores[0] = 90   # 可変性:機能する(文字列はTypeErrorを発生させます)
Junoインデックス処理とスライシング 位置は0で開始します。負の数は末尾から逆算します。したがってscores[-1]は最後のものです。scores[1:3]のようなスライスは、位置1と2を含む新しいリストを渡します。私が一瞬かかった部分:リストを使用して、位置に書き込むこともできます。scores[0] = 90は文字列が拒否する場所です。
Junoインデックス処理とスライシング 文字列と同じインデックス処理とスライシング、位置は0から、負は末尾から。違いは可変性です。インデックスまたはスライスに割り当て、リストを変更します。文字列はTypeErrorを発生させます。
Junoインデックス処理とスライシング 文字列のインデックス処理のように読み取りますが、割り当てることができます。スライス割り当てはリストを変更します。lst[1:3] = [10, 20, 30]は2つのアイテムを3つと交換します。意図的に到達してください。

アイテムの追加

アイテムを追加する3つの方法。append()は単一のアイテムを末尾に追加し、ほとんどいつもあなたが使用するものです。insert()は特定の位置に追加します。extend()は別のリストをマージします。

append()はO(1)償却です(リストは予備スペースを保持し、時々だけサイズ変更するため、平均コストは一定のままです)。アイテムごとにリストを構築する標準的な方法です。insert()はO(n)です。後続要素をシフトするためです。extend()+=と同等で、ループ内で繰り返されたappend()よりも効率的です。

append()は安価です。リストが予備スペースを保持し、時々だけサイズ変更するため、平均コストはO(1)(長さに関わらず常数)のままです。insert(0, x)はトラップです:フロントへの挿入はO(n)です。すべての要素が右に1スロットシフトするため。フロント内でリストを構築することで繰り返し追加する場合、全体でO(n二乗)に変わります。フロント挿入が高速である必要があるとき、標準ライブラリのcollections.dequeを使用します。そのappendleftはO(1)です。Modules章で説明されています。extend()は1回のパスでリストを拡張し、アイテムが既にあるときにループのappend()呼び出しを打ち負かします。

python
scores = [87, 92, 74]

scores.append(65)          # [87, 92, 74, 65]
scores.insert(1, 100)      # [87, 100, 92, 74, 65]
scores.extend([55, 71])    # [87, 100, 92, 74, 65, 55, 71]

一般的な間違い:リストでappend()を行うと、リスト全体が1つのアイテムとして追加され、リスト内にリストが与えられます。代わりにextend()を使用してマージしてください:

append(x)は常にxを単一要素として追加します。リストをappend()に渡すと、ネストされたリストが得られます。別のリストのすべてのアイテムをこれにマージしたい場合はextend()を使用してください:

append(x)xが何であれ、1つの要素としてxを追加します。リストを渡すと、そのリスト全体が入れ子になります。extend(iterable)は引数をウォークして、各要素を個別に追加します。lst += otherextendと同じことを行うため、呼び出しサイトでどちらが読みやすいかを選択してください。

python
scores.append([55, 71])    # [..., [55, 71]]  ネストされたリスト、おそらく間違い
scores.extend([55, 71])    # [..., 55, 71]    マージされた、正しい
Junoアイテムの追加append()は1つのアイテムを末尾にくっつけ、ほぼ毎回あなたが到達するものです。insert()は位置にアイテムをドロップします。extend()は別のリストをマージします。古典的なスリップ:append()するリストとあなたはリスト内にリストを取得します。マージするときはextend()を使用してください。
Junoアイテムの追加append()はデフォルトです。アイテムは末尾に1つずつです。insert()は後のすべてをシフトし、より多くのコストがかかります。append()するリストとそれは入れ子になります。extend()(または+=)は代わりにアイテムをマージします。
Junoアイテムの追加append()はO(1)の償却です。insert(0, x)はO(n)です。ループ内でフロントに構築することは静かに二次になります。dequeを到達してください。append()するリストはそれ全体を入れ子にします。extend()または+=はマージです。

アイテムの削除

アイテムを削除するための4つのツール。remove()は値で検索します。pop()は位置で削除し、アイテムを返します。delは位置で削除し、戻り値はなく。clear()はリスト全体を空にします。

remove()はO(n)です:値で最初の出現をスキャンします。pop()引数なしは最後のアイテムの場合O(1)です。pop(i)他の位置ではO(n)です。要素がシフトするため。del scores[i]pop(i)と同等ですが、戻り値は破棄します。

remove(value)は値を比較し、最初にマッチを見つけるまで前からスキャンします。次に、それの後のすべてを左にシフトします。O(n)(コストはリストの長さで成長する)。pop()はO(1)で、何もシフトしません。pop(i)他の場所ではO(n)です。同じシフト理由のため。ホットループで任意の位置から削除している場合、その繰り返されたO(n)は、データを再構成するか、別のコレクションを選択するキューです。

python
scores = [87, 92, 74, 65, 91]

scores.remove(74)    # 74の最初の出現を削除
scores.pop()         # 最後のアイテムを削除して返す(91)
scores.pop(0)        # 位置0のアイテムを削除して返す(87)
del scores[1]        # 位置1で削除、戻り値なし
scores.clear()       # すべてを削除

値がリスト内にない場合、remove()ValueErrorを発生させます。確実でない場合は最初にinで確認してください:

python
if 74 in scores:
    scores.remove(74)

remove()はミスでValueErrorを発生させます。inチェックは余分なO(n)スキャンを追加するため、リストを2回歩きます。1回限りのコードではそれで問題ありません。失敗をプリチェックするのではなくキャッチするほうがよい場合は、try / except ValueErrorFiles and exceptions章で説明されています。

inその後remove()パターンは2つのO(n)スキャン、リストは2回歩きます。順序が重要でない場合、ターゲットを最後の要素と入れ替え、それをポップするのはO(1)です(定数コスト、シフトなし)。そして、メンバーシップを頻繁にテストしている場合、setはO(1)で検索します。リストはO(n)です。Tuples and sets章で説明されています。経験則:順序付けされた変更データのリスト、「それはそこにあるか」がホットな質問の瞬間のセット。

Junoアイテムの削除remove()は値で削除し、最初のマッチのみを削除し。値がそこにない場合ValueErrorを発生させます。確実でない場合は最初にinで確認してください。pop()は位置で削除し、アイテムを返します。delは位置で削除し、あなたに何も与えません。
Junoアイテムの削除remove()は最初の値マッチを削除し、ミスでValueErrorを発生させます。pop()は末尾で安価で、アイテムを返します。pop(i)他の場所は後のすべてをシフトします。delは位置で削除、戻り値なし。
Junoアイテムの削除remove()pop(i)末尾から離れてはO(n)シフト;末尾からのpop()だけがO(1)です。「それはそこにあるか」がホットパスの場合、setはリストがO(n)のO(1)で行います。remove()の前にinでプリチェックするとリストを2回歩きます。

ソート

sorted()は新しいソート済みリストを返し、元のリストはそのまま残ります。.sort()はリストを所定位置でソートし、Noneを返します。その違いは聞こえるよりも重要です。

sorted()は安全なデフォルトです。元のものを変更しません。.sort()は所定位置を変更し、Noneを返します。これは一般的なトラップです。.sort()の結果を割り当てると、Noneが得られます。ソート済みリストではありません。元のままにしたい場合はsorted()を使用してください。ソート済みバージョンが必要な場合は.sort()を使用してください。

Pythonのソートは安定:等しい要素は元の相対順序を保持します。これにより、1つのキーでソートしてから別のキーでソートし、最初の順序がタイブレーカーとして生き残ることができます。また、ほぼソート済みデータで高速です。スクラッチからのソートのO(n log n)に対してO(n)(線形)に近いため、ほぼ順序付けされたリストの再ソートは安価です。.sort()は意図的にNoneを返します:リストを所定位置で変更するメソッドは、それも返さないというのが慣例であり、x = lst.sort()を書くのを止めます。そして静かにNoneを得ます。sorted()はリストだけでなく、任意のイテラブルを取得し、常に新しいリストを返します。

python
scores = [87, 42, 96, 55, 71]

ranked = sorted(scores)            # [42, 55, 71, 87, 96] (新しいリスト)
scores.sort()                      # 所定位置でソート、Noneを返す
scores.sort(reverse=True)          # [96, 87, 71, 55, 42]

result = scores.sort()             # resultはNoneであり、ソート済みリストではない
Junoソートsorted()は新しいソート済みリストを与え、元のリストを単独で残します。.sort()はリストを再配置し、Noneを返すため、x = scores.sort()はあなたをNoneで着地させます。リストではありません。その正確な間違いを1回以上の後に行いました。それは固まりました。
Junoソートsorted()は安全なデフォルトです。元に触れません。.sort()は所定位置でソートし、Noneを返すため、結果の割り当ては記憶するトラップです。元を無傷にする必要がある場合はsorted()を選択してください。
Junoソート ソートは安定しているため、最初にセカンダリキーでソート、その後プライマリソートしてください。タイは早期順序を保持します。ほぼソート済みデータで線形実行のため、再ソートは安価です。.sort()は設計によりNoneを返します。sorted()は任意のイテラブルを取得し、新しいリストを返します。

便利な操作

Pythonには、リストで直接機能する組み込みツールのセットがあります。len()sum()min()、およびmax()は、あなたが常に到達する4つです。

組み込みシーケンス関数は任意のリストで機能します。inはリストの線形スキャンです。繰り返されたメンバーシップテストが高速である必要がある場合は、セットに変換します。.index()は値が見つからない場合ValueErrorを発生させます。

len()sum()min()、およびmax()はリストだけでなく、任意のイテラブルで機能するため、同じ呼び出しはリスト、タプル、またはジェネレータを読み取ります。重要なコスト注記:in.index()の両方は前から後ろへスキャンします。O(n)(コストは長さで成長する)。リストには内容のインデックスがないため。ループ内で繰り返されたメンバーシップチェックはそこで加算され、setが修正です。1つのシャープエッジ:sum()0から開始するため、数値を追加します。文字列ではなく。文字列を結合するには"".join()を使用します。Strings章で説明されています。

python
scores = [87, 92, 74, 65, 91]

len(scores)          # 5
sum(scores)          # 409
min(scores)          # 65
max(scores)          # 92
scores.count(87)     # 1
scores.index(74)     # 2
74 in scores         # True
74 not in scores     # False
scores.copy()        # 浅いコピー
scores.reverse()     # 所定位置で逆順
Juno便利な操作len()sum()min()、およびmax()はすべてリストで直接機能します。セットアップなし。inは何かが存在するかどうかを尋ね、.count()は何回かを数え、そして.index()は最初のマッチの位置を見つけます。
Juno便利な操作 組み込み関数はあらゆるリストで機能し、シーケンス関数はあらゆるイテラブルで機能します。inは線形スキャンであるため、繰り返されたメンバーシップテストの場合、セットに変換してください。.index()は値が見つからない場合ValueErrorを発生させます。
Juno便利な操作len()sum()min()max()はリストだけでなく、あらゆるイテラブルを取得します。in.index()は両方ともO(n)スキャン,ホットなメンバーシップチェックはsetを望む。そしてsum()0から開始するため、文字列について"".join()に到達してください。

反復処理

forループはリストを一度に1つのアイテムで移動します。forの後の変数は順番に各アイテムを受け取ります。位置も必要な場合、enumerate()は手動カウンターがなく両方を与えます。

for item in listはリストのイテレータを呼び出し、各ステップでそれを進めます。enumerate(iterable, start=0)はイテレータをラップし、(index, value)ペアを返します。enumerate()を使用することは、手動でカウンター変数を保持するよりもクリーンで、エラーが少ないです。

enumerate()はループのときに(index, value)ペアを返します。これがfor i, item in enumerate(...)が読みやすい理由です:各ペアは2つの名前に解凍されます。start引数は、ループが実際にリスト内で読む場所を変更することなく、表示目的でのみカウンターをシフトします(したがってstart=1はそれから番号を付けます)。それを手でロール寸法から優先する理由は速度ではなく、バンプする別個のカウンターは1つのことをするのを忘れています。そしてenumerate()は同期できません。

python
players = ["太郎", "花子", "次郎"]

for player in players:
    print(player)

for i, player in enumerate(players, start=1):
    print(f"{i}. {player}")
# 1. 太郎
# 2. 花子
# 3. 次郎

forenumerate()Control flow章で完全に扱われています。短いバージョン:for player in playersはアイテムごとに1回実行し、enumerate()はすべての反復で位置と値の両方を与えます。

Juno反復処理 `for`ループはリストを一度に1つのアイテムで移動し、`for`の後の名前はその各ターンのアイテムになります。位置も必要な場合、`enumerate()`は両方を与えるため、カウンターを自分で保持する必要はありません。それを数えるのは多くの-オフ-バイ-ワンのスリップを削除しました。
Juno反復処理 `for item in list`は各アイテムを順番に訪問します。`enumerate(iterable, start=0)`は`(index, value)`ペアを返し、手動でカウンター管理するよりもクリーンで、エラーが少ないです。1ベースの番号付けが必要な場合は`start=1`を使用してください。
Juno反復処理 `enumerate()`は`(index, value)`ペアを返し、2つの名前に直接解凍しています。`start`は表示カウンターのみをシフトし、読み取り位置ではありません。勝利は速度ではなく、手動カウンターは同期できず、これはできません。

ネストされたリスト

リストは他のリストを含むことができます。これは、グリッドまたはテーブルを表す方法です:行のリスト、各行が値のリストです。2つの角括弧のセットがアイテムにアクセスします:最初が行を選択し、2番目が列を選択します。

ネストされたリストはリストの参照のリストです。各内部リストは独立したオブジェクトです。チェーンされたサブスクリプトでアクセス:grid[row][col]。内側のリストを変更すると、外側のリストに影響を与えます。外側のリストは同じオブジェクトへの参照を保持しているためです。

ネストされたリストは真の2D配列ではありません。外側のリストは内側のリストへの参照を保持し、それぞれ独立したオブジェクトであるため、行は異なる長さを持つことができ、異なる型を保持することができます。grid[1][2]は2つの検索です:行を選択し、その中のインデックスを索引します。その結果として捕捉する事柄:外側のリストの浅いコピー(.copy()が作成する種類)は外側のコンテナを複製しますが、同じ内側のリストをまだ指しています。内側の行の変更は両方のコピーに表示されます。下記の可変性セクションはそれを具体的にします。

python
grid = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

grid[0]       # [1, 2, 3]
grid[1][2]    # 6  (行1、列2)
Junoネストされたリスト リストはリストを保持できます。グリッドまたはテーブルを構築する方法です:行のリスト、各行がリスト。2つの括弧のセットは内部に到達します。`grid[1][2]`は、最初が行を選択し、2番目が選択します。
Junoネストされたリスト ネストされたリストは、他のリストへの参照のリストであり、各内側のリストは独立したオブジェクトです。チェーンされたサブスクリプトで到達してください。`grid[row][col]`。外側のリストは参照のみを保持しているため、内側のリストを変更することはそれを指す各名前を通じて表示されます。
Junoネストされたリスト 真の2D配列ではありません。外側のリストは参照を保持しているため、内側の行は長さと型を変えることができます。`grid[1][2]`は2つの検索です。浅いコピーは外側のリストを複製しますが、内側のリストを共有します。トラップはセクションです。

可変性:落とし穴

これはほぼ全員を驚かせます。リストを新しい変数に割り当てることはコピーを作成しません。両方の名前は同じリストをポイントします。1つを変更すると、もう1つを変更します。独立したコピーを取得するには、明示的に要求する必要があります。

リスト割り当ては参照をコピーします。オブジェクトではなく。両方の名前は同じ基礎的なリストをポイントします。いずれかの名前を通じた変更は同じデータに影響を与えます。独立したデータが必要な場合は、.copy()list()、または完全なスライス[:]で明示的にコピーしてください。

b = aは2番目の名前を同じリストオブジェクトにポイントするため、bを通じた変更はaが見るオブジェクトにも着地します。.copy()a[:]浅いコピーを作成します:新しい外側のリストは元のものと同じ要素参照を保持しています。平坦なリストの不変値(変更できない数値、文字列、もの)の場合、それはあなたが必要とするすべてです。ネストされたリストの場合、内側のリストはまだ元のと複製の間で共有されているため、落とし穴です。1つを通じて行を編集することは他の中に表示されます。

python
a = [1, 2, 3]
b = a            # bはコピーではありません;それは同じリストをポイントします

b.append(4)
print(a)         # [1, 2, 3, 4]  (変更:aおよびbは同じリスト)
python
b = a.copy()    # 独立したコピー
b = list(a)     # 同じ結果
b = a[:]        # また同じ

# ネストされたリストはまだ内側のオブジェクトを共有:
matrix = [[1, 2], [3, 4]]
copy = matrix.copy()

copy[0].append(99)
print(matrix)   # [[1, 2, 99], [3, 4]]  (内側のリストが共有された)

内側のリストを手動で複製する必要がある入れ子の構造の場合、または標準ライブラリからcopy.deepcopy()を使用します。Modules章で説明されています。

Juno可変性:落とし穴b = aはコピーを作成しません。両方の名前は同じリストをポイントし、1つを通じた変更は他に表示されます。独立したリストについては、あなたは求める必要があります。.copy()list(a)、またはa[:]。これは最初に誰もがほぼ驚いており、私も含まれます。
Juno可変性:落とし穴 割り当ては参照をコピー,リストではなく。したがって`b = a`は1つのオブジェクトを残す2つの名前,そしていずれかを通じた変更は同じデータにヒットします。`.copy()`、`list(a)`、または`a[:]`で明示的にコピーしてください。独立性が必要な場合。
Juno可変性:落とし穴 `b = a`は1つのオブジェクトを共有します。`.copy()`と`a[:]`は浅いコピーを作成します。新しい外側のリストは同じ内側の参照を超えています。不変値のフラットリストはその方法で安全です。ネストされたリストはそれらの行を共有します。内側も独立している必要な場合はcopy.deepcopy()に到達してください。

更多方法

メソッド動作
.append(item)末尾に追加
.insert(i, item)位置iに挿入
.extend(iterable)イテラブルからすべてのアイテムを追加
.remove(value)値の最初の出現を削除
.pop(i)位置iのアイテムを削除して返す(デフォルト:最後)
.clear()すべてのアイテムを削除
.index(value)最初の出現の位置
.count(value)出現数
.sort()所定位置でソート
.reverse()所定位置で逆順
.copy()浅いコピーを返す

実践

スコアトラッカーを構築:結果を追加、ソート、概要を印刷します。

python
scores = []

scores.append(87)
scores.append(54)
scores.append(92)
scores.append(67)
scores.append(45)

scores.sort(reverse=True)

print(f"Ranked scores: {scores}")
print(f"Highest: {scores[0]}")
print(f"Lowest:  {scores[-1]}")
print(f"Average: {sum(scores) / len(scores):.1f}")
print(f"Top 3:   {scores[:3]}")

名前とスコアの2つの平行なリスト:トップパフォーマーを見つけ、順位付けされた結果を印刷します。

python
names = ["太郎", "花子", "次郎", "四郎"]
scores = [87, 74, 92, 55]

best_score = max(scores)
best_index = scores.index(best_score)
best_player = names[best_index]

print(f"Top player: {best_player} ({best_score})")
print(f"Average:    {sum(scores) / len(scores):.1f}")

ranked = sorted(scores, reverse=True)
print(f"Distribution (ranked): {ranked}")

for rank, score in enumerate(ranked, start=1):
    print(f"  Rank {rank}: {score}")

エイリアシングとコピーの違い、ネストされたリストの浅いコピーと深いコピーの違いを実演します。

python
# エイリアシング:bはコピーではない
a = [1, 2, 3]
b = a
b.append(4)
print(a)    # [1, 2, 3, 4]  (同じオブジェクト)

# 浅いコピー:外側のリストは独立、内側のリストは共有
matrix = [[1, 2, 3], [4, 5, 6]]
shallow = matrix.copy()
shallow[0].append(99)
print(matrix)    # [[1, 2, 3, 99], [4, 5, 6]]  (内側のリスト共有)

# forループでの手動の深いコピー(インポート不要)
matrix = [[1, 2, 3], [4, 5, 6]]
deep_copy = []
for row in matrix:
    deep_copy.append(row[:])    # 各内側のリストを明示的にコピー

deep_copy[0].append(99)
print(matrix)    # [[1, 2, 3], [4, 5, 6]]  (変更なし)