リストの生成 | リストの定義と操作 | Python本格超入門

スポンサーリンク
スポンサーリンク
amazon
スマイルSALE
--:--:--
~
ad. 価格範囲を指定して商品を探せます

リストの生成

Pythonにおけるリスト(list)は、複数のデータを1つの変数にまとめて順序通りに管理するための、最も頻繁に使われるデータ構造(配列)です。

リストは、文字列、数値、真偽値、さらには別のリストや辞書など、あらゆるデータ型を柔軟に格納できます。本記事では、基本的なリストの生成方法から、インデックスによる要素へのアクセス、実務で初心者が最も陥りやすい「参照とコピー」のメモリ上の罠までを徹底的に解説します。

リストの基本的な生成方法

Pythonでリストを作るには、角括弧 [] を使用し、中に入れる要素をカンマ(,)で区切ります。

# 1. 空のリストを生成(後から要素を追加していく土台)
empty_list = []
# または empty_list = list() と書くことも可能です

# 2. 同一のデータ型をまとめたリスト
fruits = ["apple", "banana", "cherry"]

# 3. 異なるデータ型(数値、文字列、ブール値)が混在したリスト
#  Pythonの仕様上可能ですが、実務ではデータ処理が複雑になるため推奨されません
mixed_list = [1, "apple", True]

リストの要素数を計測する(len関数)

リストの中にデータが何件格納されているか(リストの長さ)を取得するには、組み込み関数である len() を使用します。

fruits = ["apple", "banana", "cherry"]
# len() の引数にリストを渡します
print(len(fruits))  # 出力: 3

リスト生成の動的バリエーション

手動で要素を1つずつタイピングする以外に、Pythonの標準機能を駆使してルールに基づいたリストを自動生成する強力なアプローチが2つあります。

  • range() 関数との連携: 連続した整数のシーケンスを高速に生成し、list() で囲むことで一瞬で数値リストへ変換します。
  • リスト内包表記: ループ処理(`for`)と数式を1行の角括弧内に閉じ込め、既存のデータを加工した新しいリストをエレガントに構築します。
# パターンA: range() を用いた 0〜9 の数値リスト一括生成
# 引数の終端(10)は含まれない性質(未満)を持ちます
numbers = list(range(10))
print(numbers)  # 出力: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# パターンB: リスト内包表記を用いた 1〜5 の平方数(2乗)リスト生成
squares = [x ** 2 for x in range(1, 6)]
print(squares)  # 出力: [1, 4, 9, 16, 25]

要素へのアクセス:正方向・逆方向インデックス

リスト内の特定のデータを取り出すには、要素の並び順を示すインデックス(添字)を指定します。Pythonのインデックスは**先頭が「0」から始まる**ルールです。

また、末尾から数えた方が早いケースのために、マイナス(`-`)の数値を指定して後ろから逆走してアクセスする「負のインデックス」も標準サポートされています。

fruits = ["apple", "banana", "cherry"]

# 正方向インデックス(0からカウント)
first_item = fruits[0]  # 先頭の要素
second_item = fruits[1] # 2番目の要素

# 負方向インデックス(-1が末尾)
last_item = fruits[-1]  # 最後の要素
second_last = fruits[-2] # 後ろから2番目の要素

print(first_item)  # 出力: apple
print(last_item)   # 出力: cherry

実務の最大の罠:「参照のコピー」と「浅いコピー」の違い

Pythonのリストを扱う上で、**全員が一度は引っかかる致命的な仕様**が、変数への代入時の挙動です。リストを単に別の変数へ = で代入すると、データそのものではなく、メモリ上の**「格納場所のアドレス(参照)」**だけが複製されます。

# バグの原因:単なる代入(参照の共有)
list_origin = [1, 2, 3]
list_alias = list_origin  # アドレスだけがコピーされる

list_alias[0] = 99
# 別名(list_alias)を書き換えたはずが、元のリストも書き換わってしまう!
print(list_origin)  # 出力: [99, 2, 3]


# 正しいアプローチ:独立したリストの複製(浅いコピー: Shallow Copy)
list_base = [1, 2, 3]
# スライス構文 [:] を使うか、list_base.copy() メソッドを使用します
list_backup = list_base[:]

list_backup[0] = 500
# バックアップ側をいくら変更しても、元のリストのメモリは完全に保護されます
print(list_base)    # 出力: [1, 2, 3]
print(list_backup)  # 出力: [500, 2, 3]

まとめ

  • #0始まりの原則を叩き込む: リストの先頭インデックスは `1` ではなく `0` です。末尾の要素に最短距離でアクセスしたい場合は、要素数をわざわざ計算せずに `[-1]` を指定するテクニックを癖付けましょう。
  • rangeと内包表記によるコードの軽量化: 大量の連番や規則的なデータを扱う際、泥臭く手動入力するのではなく、`list(range())` やリスト内包表記を活用することで、バグが混入しにくいクリーンなシステムを記述できます。
  • 破壊的な副作用を防ぐコピー設計: 関数にリストを引数として渡す際や、データを一時退避させたい際は、安易に `A = B` と書かないように注意してください。必ず `B[:]` や `.copy()` を選択し、メモリ上の実態まで複製する防衛プログラミングの意識を持ちましょう。