Pythonのリストは、複数の値をまとめて扱える、とても便利なデータ構造です。
本記事では、追加・変更・削除といった「よく使う操作」に絞って、初心者の方にもわかりやすく解説していきます。
実際のコード例や図解を交えながら進めますので、Pythonを始めたばかりの方でも安心して読み進めてください。
リストの作成と初期化
まずは、Pythonのリストをどのように作るのかから確認していきます。
リストの作成方法を理解しておくと、あとで学ぶ追加・変更・削除がぐっと理解しやすくなります。
空のリストと要素ありリストの作成
ここがスタートラインなので、少し丁寧に押さえておきましょう。

Pythonでは、角かっこ[]を使ってリストを表現します。
リストの中に何も入っていなければ空リスト、値をカンマで区切って並べれば、要素を持つリストになります。
空のリストを作成する
空のリストは、値を後から追加していきたいときの出発点になります。
書き方はとてもシンプルです。
# 空のリストを作成
numbers = [] # もっともよく使われる書き方
names = list() # listコンストラクタを使う書き方
print(numbers) # []
print(names) # []
[]
[]
角かっこだけ[]を書けば空のリストになります。
多くの場合、この書き方が最も読みやすく、実務でもよく使われます。
要素を含むリストを作成する
あらかじめ値がわかっている場合は、リストを作るタイミングで要素を並べてしまうと便利です。
# 数値のリスト
scores = [70, 85, 90]
# 文字列のリスト
fruits = ["apple", "banana", "orange"]
# 異なる型を混在させることも可能
mixed = [1, "hello", 3.14]
print(scores)
print(fruits)
print(mixed)
[70, 85, 90]
['apple', 'banana', 'orange']
[1, 'hello', 3.14]
Pythonのリストは、整数、文字列、浮動小数点数などを混在させることができる柔軟なコンテナです。
その一方で、後々扱いやすくするためには、現場のコードでは同じ種類のデータだけを入れることが多いという点も覚えておくと良いです。
rangeを使ったリスト生成
大量の連番をリストにしたい場面は意外と多くあります。
例えば、1から10までの数字、0から99までの番号、といったケースです。
そうしたときに便利なのがrangeです。

rangeをそのまま使う場合と、リストにする場合
rangeは「0からn-1までの連続した整数を表すオブジェクト」ですが、見た目は少し特殊です。
リストとして扱いたい場合はlist()で変換します。
# rangeオブジェクトの作成
r = range(5) # 0, 1, 2, 3, 4 を表す
print(r) # range(0, 5) と表示されるだけで、中身は直接は見えない
# listに変換して中身を確認
nums = list(r)
print(nums) # [0, 1, 2, 3, 4]
range(0, 5)
[0, 1, 2, 3, 4]
rangeの3つの書き方
rangeには「開始値・終了値・ステップ」の3つの指定方法があります。
典型的なパターンごとに見てみます。
# 0 から 4 (終了値は含まない)
a = list(range(5)) # [0, 1, 2, 3, 4]
# 1 から 5
b = list(range(1, 6)) # [1, 2, 3, 4, 5]
# 0 から 10 まで 2 ずつ増える
c = list(range(0, 11, 2)) # [0, 2, 4, 6, 8, 10]
print(a)
print(b)
print(c)
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5]
[0, 2, 4, 6, 8, 10]
終了値が「含まれない」という挙動は、初めのうちは戸惑いやすいので、range(開始, 終了_含まない, ステップ)という形でセットで覚えておくと良いです。
二次元リストの基本
リストは、要素としてリストを含むことができます。
このような、「リストの中にリストが入っている形」を二次元リストと呼びます。
表形式のデータや、座標などを扱うのに便利です。

二次元リストの作り方とアクセス方法
まずは、3行3列の数表を二次元リストで表してみます。
# 3x3 の二次元リストを作成
matrix = [
[1, 2, 3], # 0行目
[4, 5, 6], # 1行目
[7, 8, 9] # 2行目
]
print(matrix) # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(matrix[0]) # 1行目 [1, 2, 3]
print(matrix[1][2]) # 2行目3列目の要素 6
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[1, 2, 3]
6
二次元リストの要素にアクセスするときはmatrix[行インデックス][列インデックス]という形で角かっこを2つ並べて指定します。
0から数える点は一次元リストと同じです。
二次元リストで注意したい初期化
二次元リストを初期化するときに、よくあるミスがあります。
代表的な例を見てみましょう。
# よくある NG パターン
rows, cols = 3, 3
ng_matrix = [[0] * cols] * rows # 3行3列のつもり
ng_matrix[0][0] = 1
print(ng_matrix)
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
1つだけ変更したつもりが、すべての行の先頭要素が同時に変わってしまっています。
これは、同じリストオブジェクトを3回参照しているだけで、実体が1つしかないためです。
正しい初期化方法の一例は、リスト内包表記を使うことです。
# 正しい二次元リストの初期化
rows, cols = 3, 3
ok_matrix = [[0 for _ in range(cols)] for _ in range(rows)]
ok_matrix[0][0] = 1
print(ok_matrix)
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]
各行ごとに別々のリストを作ることで、意図したとおりに個別の行を変更できるようになります。
リストへの追加操作
次に、既存のリストに対して、要素を増やしていく方法を見ていきます。
Pythonには、append・insert・extend・プラス演算子という主な4つの追加方法があります。
それぞれの違いを整理しながら理解していきます。
appendで要素を末尾に追加

appendは、リストの末尾に1つの要素を追加するメソッドです。
最もよく使うリスト操作の1つなので、挙動をしっかり押さえておきましょう。
# appendで要素を1つずつ追加
numbers = [] # 空のリスト
numbers.append(10) # [10]
numbers.append(20) # [10, 20]
numbers.append(30) # [10, 20, 30]
print(numbers)
[10, 20, 30]
appendは「1つの要素」を追加する点がポイントです。
もしリストそのものをappendすると、そのリストが「1つの要素」として入ります。
data = [1, 2, 3]
data.append([4, 5]) # [4, 5] 全体が1要素として追加される
print(data)
print(len(data)) # 要素数は4
[1, 2, 3, [4, 5]]
4
複数の要素を「ばらして」追加したい場合は、後述するextendか、プラス演算子を使う必要があります。
insertで指定位置に要素を追加

insertは、リストの任意の位置に要素を挿入するメソッドです。
順番が重要なリストでは、途中に要素を足したい場面がよくあります。
# insertで指定位置に挿入
numbers = [10, 30, 40]
numbers.insert(1, 20) # インデックス1の位置に20を挿入
print(numbers) # [10, 20, 30, 40]
numbers.insert(0, 5) # 先頭に5を挿入
print(numbers) # [5, 10, 20, 30, 40]
[10, 20, 30, 40]
[5, 10, 20, 30, 40]
インデックスがリストの長さ以上の場合は、末尾に追加されるという点も押さえておきましょう。
numbers = [1, 2, 3]
numbers.insert(100, 4) # 実質的に末尾に追加される
print(numbers)
[1, 2, 3, 4]
extendでリスト同士を結合

extendは、リストの末尾に、他のイテラブル(リストなど)の要素を「ばらして」追加するメソッドです。
a = [1, 2]
b = [3, 4]
a.extend(b) # bの要素がaの末尾に追加される
print(a) # [1, 2, 3, 4]
print(b) # b自体は変わらない
[1, 2, 3, 4]
[3, 4]
appendとの違いがよく問われるので、対比して確認しておきます。
a = [1, 2]
b = [3, 4]
a.append(b)
print("append:", a)
a = [1, 2]
a.extend(b)
print("extend:", a)
append: [1, 2, [3, 4]]
extend: [1, 2, 3, 4]
「リストをネストしたいならappend」「中身を展開して結合したいならextend」という覚え方がわかりやすいです。
プラス演算子でリストを結合
+演算子を使うと、2つのリストを結合した新しいリストを作成できます。
元のリストは変更されません。

a = [1, 2]
b = [3, 4]
c = a + b # a と b を結合した新しいリスト
print("a:", a)
print("b:", b)
print("c:", c)
a: [1, 2]
b: [3, 4]
c: [1, 2, 3, 4]
元のリストを変えたくない場合はプラス演算子、新しいリストを作らずにその場で伸ばしたい場合はextendという使い分けが便利です。
リストの変更と削除
ここからは、既にあるリストの中身を書き換えたり、不要な要素を削除したりする方法を解説します。
インデックスやスライスを組み合わせることで、かなり柔軟な編集が可能になります。
インデックス指定で要素を変更

リストの特定の位置にある要素を変更するには、インデックス演算子[]を左辺に書くだけです。
numbers = [10, 20, 30]
numbers[1] = 99 # インデックス1(2番目)を99に変更
print(numbers)
[10, 99, 30]
マイナスのインデックスを使うと、末尾から数える指定もできます。
data = [1, 2, 3, 4]
data[-1] = 100 # 最後の要素を100に変更
data[-2] = 200 # 最後から2番目の要素を200に変更
print(data)
[1, 2, 200, 100]
スライスで複数要素を一括変更

スライスはlist[開始:終了]のような書き方で、一部分を抜き出す機能ですが、代入に使うことで複数要素を一度に置き換えることもできます。
numbers = [1, 2, 3, 4, 5]
# インデックス1〜3(4は含まない)をまとめて置き換え
numbers[1:4] = [10, 20, 30]
print(numbers)
[1, 10, 20, 30, 5]
スライス代入の特徴は、置き換える要素数と、新しい要素数が一致している必要はないという点です。
data = [1, 2, 3, 4, 5]
# 2つの要素を3つで置き換え (長くなる)
data[1:3] = [100, 200, 300]
print(data) # [1, 100, 200, 300, 4, 5]
# 逆に3つを1つで置き換え (短くなる)
data[1:4] = [99]
print(data) # [1, 99, 4, 5]
[1, 100, 200, 300, 4, 5]
[1, 99, 4, 5]
このように、スライス代入は「一括変更」と「範囲削除+挿入」を同時に行う強力なテクニックです。
del文で要素や範囲を削除

del文は、指定したインデックスやスライス範囲を削除するための構文です。
numbers = [10, 20, 30, 40, 50]
# 2番目の要素を削除
del numbers[1]
print(numbers) # [10, 30, 40, 50]
# インデックス1〜2を削除(3は含まない)
del numbers[1:3]
print(numbers) # [10, 50]
[10, 30, 40, 50]
[10, 50]
delは、リスト全体に対しても使うことができます。
data = [1, 2, 3]
del data # data という変数自体が削除される
# print(data) # ここで参照するとエラーになる
このようにdelは「変数名の削除」と「リスト中の要素の削除」の両方に使えるため、文脈に応じて意味が変わる点に注意してください。
removeとpopで要素を削除
要素を削除するときに、「値で指定するか」「インデックスで指定するか」で使うメソッドが変わります。

removeで「値」を指定して削除
removeは、指定した値と一致する最初の1つだけを削除します。
numbers = [10, 20, 30, 20, 40]
numbers.remove(20) # 最初の20だけ削除
print(numbers)
[10, 30, 20, 40]
指定した値がリストに存在しない場合はValueErrorが発生します。
data = [1, 2, 3]
# data.remove(99) # 99は存在しないので ValueError
見つからなかったときにエラーを出したくない場合は、inで存在確認をしてからremoveを呼ぶと安全です。
popで「位置」を指定して削除しつつ取り出す
popは、指定したインデックスの要素を取り出し、その要素をリストから削除するメソッドです。
インデックスを省略すると、末尾の要素が対象になります。
numbers = [10, 20, 30]
value = numbers.pop(1) # インデックス1の要素(20)を取り出して削除
print("取り出した値:", value)
print("残ったリスト:", numbers)
last = numbers.pop() # インデックス省略 → 末尾(30)が対象
print("最後の値:", last)
print("最終的なリスト:", numbers)
取り出した値: 20
残ったリスト: [10, 30]
最後の値: 30
最終的なリスト: [10]
スタックや履歴のように「最後に追加したものから順に取り出す」処理では、appendとpop()の組み合わせがよく使われます。
clearでリストを空にする

clearは、リストの中身をすべて削除して空にするメソッドです。
変数自体は残したまま、中身だけリセットしたいときに便利です。
items = [1, 2, 3, 4]
items.clear()
print(items) # []
[]
del items[:]と同様の効果ですが、clearのほうが意図が明確で読みやすいというメリットがあります。
リストの便利な操作
ここまでで、リストに対する基本的な追加・変更・削除はひと通り扱いました。
最後に、実用上よく使う「便利操作」をまとめて紹介します。
これらを押さえておくと、日常的なPythonコーディングがぐっと楽になります。
lenでリストの長さを取得

len関数は、リストの要素数(長さ)を返す標準関数です。
numbers = [10, 20, 30, 40]
length = len(numbers)
print(length)
4
ループ処理や、後ろから要素にアクセスしたいときなど、lenは非常に頻繁に登場するので、自然に使えるようになっておきましょう。
inで要素の存在を確認

in演算子を使うと、リストの中にある値が含まれているかどうかを真偽値で判定できます。
numbers = [10, 20, 30]
print(20 in numbers) # True
print(99 in numbers) # False
True
False
removeを使う前にinで存在を確認しておくと、エラーを防げます。
items = ["apple", "banana", "orange"]
target = "banana"
if target in items:
items.remove(target)
print(target, "を削除しました")
else:
print(target, "はリストにありません")
print(items)
banana を削除しました
['apple', 'orange']
sortとsortedでリストを並び替え

リストを昇順や降順に並び替えたいときは、メソッドのsortと、組み込み関数のsortedを使います。
sortでリスト自体を並び替える
sortメソッドは、対象のリストそのものの順番を並び替えます(破壊的変更)。
numbers = [3, 1, 4, 2]
numbers.sort() # 昇順に並び替え
print(numbers) # [1, 2, 3, 4]
numbers.sort(reverse=True) # 降順に並び替え
print(numbers) # [4, 3, 2, 1]
[1, 2, 3, 4]
[4, 3, 2, 1]
sortedで新しい並び替え済みリストを作る
sorted関数は、元のリストを変更せずに、新しい並び替え済みリストを返す関数です。
numbers = [3, 1, 4, 2]
ascending = sorted(numbers) # 昇順の新しいリスト
descending = sorted(numbers, reverse=True) # 降順の新しいリスト
print("元のリスト:", numbers)
print("昇順:", ascending)
print("降順:", descending)
元のリスト: [3, 1, 4, 2]
昇順: [1, 2, 3, 4]
降順: [4, 3, 2, 1]
「元のリストを保持したい → sorted」「その場で並び替えてよい → sort」という基準で選ぶとわかりやすいです。
スライスで部分リストを取り出す

スライスは先ほど「一括変更」で登場しましたが、部分リストを取り出す機能としても非常に重要です。
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[2:5]) # インデックス2〜4 → [2, 3, 4]
print(numbers[:5]) # 先頭〜4 → [0, 1, 2, 3, 4]
print(numbers[5:]) # 5〜末尾 → [5, 6, 7, 8, 9]
print(numbers[-3:]) # 最後の3つ → [7, 8, 9]
[2, 3, 4]
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[7, 8, 9]
[開始:終了:ステップ]という3つ目のパラメータを使うと、一定間隔で要素を飛ばしながら取り出すこともできます。
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nums[::2]) # 先頭から2つおき → [0, 2, 4, 6, 8]
print(nums[1::2]) # インデックス1から2つおき → [1, 3, 5, 7, 9]
[0, 2, 4, 6, 8]
[1, 3, 5, 7, 9]
スライスは、「取り出し」と「一部だけ変更」の両方に使える万能ツールなので、慣れておくとPythonのコードが格段に書きやすくなります。
まとめ
Pythonのリストは、作成・追加・変更・削除・検索・並び替え・部分取り出しまでを1つでこなせる、非常に強力なデータ構造です。
本記事では、空リストから二次元リストまでの基本的な作り方、append・insert・extend・+ による追加、インデックスやスライス、del・remove・pop・clearによる変更と削除、さらにlen・in・sort/sorted・スライスといった便利操作までを一通り解説しました。
ここで紹介した操作を何度か手を動かして試してみれば、日常的なPythonプログラミングで必要なリスト操作のほとんどは不自由なく扱えるようになります。
