リスト
変数は1つの値しか保持できません。リストは複数の値を順番に、1つの名前で保持します。リーダーボードは順位付けされたスコアの並びです。クイズは質問の集まりです。関連する値のグループを管理する必要が出てきたら、リストが必要です。
リストの作成
角括弧の中に、カンマで区切られた値を並べます。リストはあらゆる型を混在させて保持でき、空のリストも有効で、後から徐々に作り上げる出発点としてよく使われます。
scores = [87, 92, 74, 65, 91]
players = ["さくら", "ひろし", "ゆうこ"]
mixed = ["さくら", 87, True, 3.14] # 任意の型、ただし一般的ではない
empty = []インデックスとスライス
リストは文字列と同じ番号付けを使います。位置は0から始まり、負の数は末尾から数えます。任意の項目を位置で読み取れます。リストはミュータブルなので、特定の位置に書き込むこともできます。
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となる)項目の追加
項目を追加する3つのメソッドがあります。append() は末尾に1つの項目を追加し、ほとんどの場合これを使うことになります。insert() は特定の位置に追加します。extend() は別のリストを統合します。
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() を使って統合しましょう:
scores.append([55, 71]) # [..., [55, 71]] ネストされたリスト、おそらく間違い
scores.extend([55, 71]) # [..., 55, 71] 統合された、正解項目の削除
項目を削除する4つのツールがあります。remove() は値で検索します。pop() は位置で削除し、その項目を返してくれます。del は位置で削除しますが、戻り値はありません。clear() はリスト全体を空にします。
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 でチェックしましょう:
if 74 in scores:
scores.remove(74)ソート
sorted() は全く新しいソートされたリストを返し、元のリストはそのままにします。.sort() はリストをその場でソートし、None を返します。その違いは聞こえる以上に重要です。
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で、ソートされたリストではない便利な操作
Pythonにはリストに直接動作する組み込みツールのセットがあります。len()、sum()、min()、max() の4つは常に使うことになるでしょう。
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() # その場で反転反復処理
for ループはリストを一度に1項目ずつ処理します。for の後の変数は、各項目を順番に受け取ります。位置も必要な場合は、enumerate() が手動カウンタなしで両方を提供してくれます。
players = ["さくら", "ひろし", "ゆうこ"]
for player in players:
print(player)
for i, player in enumerate(players, start=1):
print(f"{i}. {player}")
# 1. さくら
# 2. ひろし
# 3. ゆうこforループとenumerate
for と enumerate() は 制御フロー の章で完全に扱います。短く言うと: for player in players は項目ごとに1回実行され、enumerate() は反復ごとに位置と値の両方を提供します。
ネストされたリスト
リストは他のリストを含むことができます。これがグリッドやテーブルを表現する方法です。行のリストで、各行が値のリストです。2組の角括弧で項目にアクセスします。最初は行を選び、2番目は列を選びます。
grid = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
grid[0] # [1, 2, 3]
grid[1][2] # 6 (行1、列2)ミュータビリティ: 落とし穴
これはほぼ全員が驚きます。リストを新しい変数に代入してもコピーは作られません。両方の名前は同じリストを指します。一方を変更すると、もう一方も変わります。独立したコピーを得るには、明示的にそれを求める必要があります。
a = [1, 2, 3]
b = a # bはコピーではない; 同じリストを指している
b.append(4)
print(a) # [1, 2, 3, 4] (変更された: aとbは同じリスト)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]] (内部リストは共有されていた)その他のメソッド
| メソッド | 動作 |
|---|---|
.append(item) | 末尾に追加 |
.insert(i, item) | 位置 i に挿入 |
.extend(iterable) | イテラブルからすべての項目を追加 |
.remove(value) | 値の最初の出現を削除 |
.pop(i) | 位置 i の項目を削除して返す (デフォルト: 最後) |
.clear() | すべての項目を削除 |
.index(value) | 最初の出現の位置 |
.count(value) | 出現回数 |
.sort() | その場でソート |
.reverse() | その場で反転 |
.copy() | シャローコピーを返す |
実践
スコアトラッカーの構築: 結果を追加し、ソートし、サマリを出力します。
scores = []
scores.append(87)
scores.append(54)
scores.append(92)
scores.append(67)
scores.append(45)
scores.sort(reverse=True)
print(f"順位付けされたスコア: {scores}")
print(f"最高: {scores[0]}")
print(f"最低: {scores[-1]}")
print(f"平均: {sum(scores) / len(scores):.1f}")
print(f"トップ3: {scores[:3]}")
