【Python】リスト(list)の使い方|追加・削除・スライス・並び替え

【Python】リスト(list)の使い方|追加・削除・スライス・並び替え Python

リスト(list)は、Pythonでもっともよく使うデータ構造です。複数の値を順番に並べて持ち、あとから追加・削除・並び替えができます。[1, 2, 3]のように角かっこで書きます。

基本は簡単ですが、初心者がつまずきやすい罠が2つあります。要素を増やすappendextendの違い、そしてリストをコピーしたつもりが同じものを指していて、片方を変えるともう片方も変わるという参照の問題です。この記事では、実機のPythonで確認しながら、リストの使い方を整理します。

先に結論

  • 作成は[1, 2, 3]、空は[]、範囲からはlist(range(5))です。
  • 取り出しはlst[0]、末尾はlst[-1]、範囲はlst[1:3](スライス)です。
  • 追加は1個ならappend、複数ならextendappendはリストごと1要素として入る点に注意します。
  • 削除は値でremove、位置でpopdelです。
  • 並び替えは元を変えるsort()、新しいリストを返すsorted()です。
  • コピーはlst[:]lst.copy()。単純な代入は同じリストを指すだけなので注意します。

リストはループと一緒に使うことが多いので、forループで繰り返し処理を行う方法range関数の使い方文字列を連結・結合する方法もあわせて参考になります。

スポンサーリンク

リストを作る

リストは角かっこ[ ]で作ります。文字列や範囲(range)から作ることもできます。

create.py
# 角かっこで作る
fruits = ["りんご", "みかん", "ぶどう"]
numbers = [1, 2, 3, 4, 5]

# 空のリスト
empty = []

# 文字列から(1文字ずつ)
chars = list("abc")        # ['a', 'b', 'c']

# 範囲から連番を作る
seq = list(range(5))       # [0, 1, 2, 3, 4]

# 型が混ざってもよい
mixed = [1, "文字", True, 3.14]

実機でも、list(range(5))[0, 1, 2, 3, 4]list("abc")['a', 'b', 'c']になりました。リストには数値・文字列・真偽値など、異なる型を混ぜて入れられます。

要素にアクセスする(インデックス・スライス)

要素はインデックス(0始まり)で取り出します。マイナスで末尾から数え、範囲で複数まとめて取り出す「スライス」も使えます。

access.py
lst = [10, 20, 30, 40, 50]

lst[0]      # 10(最初)
lst[-1]     # 50(最後)

# スライス [開始:終了](終了は含まない)
lst[1:3]    # [20, 30]
lst[:2]     # [10, 20](先頭から)
lst[2:]     # [30, 40, 50](末尾まで)
lst[::2]    # [10, 30, 50](1つ飛ばし)
lst[::-1]   # [50, 40, 30, 20, 10](逆順)

実機でも、lst[-1]50lst[1:3][20, 30]lst[::-1]が逆順になりました。スライスで取り出した結果は元のリストのコピーです。スライスの一部を書き換えても、元のリストには影響しません。この性質は、後半のコピーの話につながります。

要素を追加する(append / extend / insert)

要素を増やす方法は3つあります。1個追加するappend、複数追加するextend、位置を指定するinsertです。

add.py
lst = [1, 2, 3]

# 末尾に1個追加
lst.append(4)        # [1, 2, 3, 4]

# 複数をまとめて追加(リストの中身を展開して足す)
lst.extend([5, 6])   # [1, 2, 3, 4, 5, 6]
# += でも同じ
lst += [7]           # [1, 2, 3, 4, 5, 6, 7]

# 位置を指定して挿入
lst.insert(0, 99)    # 先頭に99を入れる → [99, 1, 2, ...]

【重要】appendとextendの違い

appendextendは、どちらも「足す」ですが、結果がまったく違います。appendは渡したものを「1つの要素」として末尾に入れextendは「中身を1つずつ」足します

append-vs-extend.py
a = [1, 2]
a.append([3, 4])
print(a)   # [1, 2, [3, 4]] ← リストごと1要素として入る

b = [1, 2]
b.extend([3, 4])
print(b)   # [1, 2, 3, 4] ← 中身が展開されて足される
リストの中身を足したいなら extend

実機で確認したところ、[1, 2].append([3, 4])[1, 2, [3, 4]]になり、リストが丸ごと1つの要素として入りました。一方、extend([3, 4])[1, 2, 3, 4]と、中身が1つずつ足されました。「別のリストの要素を全部足したい」ときにappendを使うと、リストがネスト(入れ子)してしまいます。中身を足すならextend(または+=)、リストごと1要素として入れたいならappend、と使い分けてください。

要素を削除する(remove / pop / del)

削除も3つあります。値で消すremove、位置で取り出しながら消すpop、位置で消すdelです。

remove.py
lst = [10, 20, 30, 20]

# 値で削除(最初に一致した1つだけ)
lst.remove(20)    # [10, 30, 20]

# 位置で取り出して削除(戻り値あり)
lst = [10, 20, 30]
x = lst.pop()     # x=30, lst=[10, 20](省略すると末尾)
y = lst.pop(0)    # y=10, lst=[20]

# 位置で削除(戻り値なし)
lst = [10, 20, 30]
del lst[1]        # [10, 30]

# すべて削除
lst.clear()       # []

実機でも、remove(20)は最初の20だけを消し、pop()は末尾を取り出して返しました。注意点として、removeで存在しない値を指定するとValueErrorpopで範囲外の位置を指定するとIndexErrorになります。消す前にinで存在を確認すると安全です。

検索と要素数(in / index / count / len)

値が含まれるかの判定や、位置・個数・要素数の取得です。

search.py
lst = [1, 2, 2, 3]

2 in lst        # True(含まれるか)
5 not in lst    # True

lst.index(2)    # 1(最初に2がある位置)
lst.count(2)    # 2(2の個数)
len(lst)        # 4(要素数)

# 数値リストなら合計・最小・最大も
sum([1, 2, 3])  # 6
min([3, 1, 2])  # 1
max([3, 1, 2])  # 3

実機でも、2 in lstTrueindex(2)1count(2)2len4になりました。indexは最初に見つかった位置を返し、存在しないとValueErrorになります。

並び替える(sort / sorted / reverse)

並び替えには2種類あります。元のリストを直接並び替えるsort()と、新しい並び替え済みリストを返すsorted()です。

sort.py
# sorted は新しいリストを返す(元は変わらない)
nums = [3, 1, 2]
result = sorted(nums)   # [1, 2, 3]
print(nums)             # [3, 1, 2](元のまま)

# sort は元のリストを並び替える(戻り値は None)
nums.sort()             # nums 自体が [1, 2, 3] になる
nums.sort(reverse=True) # 降順 [3, 2, 1]

# key で並び替えの基準を指定(文字数順など)
words = ["bbb", "a", "cc"]
words.sort(key=len)     # ['a', 'cc', 'bbb']

# 逆順にする(並び替えではなく反転)
nums.reverse()
sortは元を変える、sortedは新しく返す

実機で確認したところ、sorted(nums)は新しいリストを返し、元のnums[3, 1, 2]のまま変わりませんでした。一方、nums.sort()nums自体を並び替えます。さらに注意したいのが、sort()の戻り値はNoneだということです。new = nums.sort()と書くと、newにはNoneが入ってしまいます。新しいリストがほしいときはsorted()を使ってください。key=lenのように基準を指定すれば、文字数順や特定の項目順にも並べられます。

【最重要】コピーと参照共有の罠

リストでもっとも注意が必要なのがこれです。b = aのような単純な代入は、リストをコピーしませんab同じリストを指すため、片方を変えるともう片方も変わります。

reference.py
a = [1, 2, 3]
b = a            # コピーではなく「同じリスト」を指す
b.append(4)
print(a)         # [1, 2, 3, 4] ← a も変わってしまう!

# 独立したコピーを作る方法
c = [1, 2, 3]
d = c[:]         # スライスでコピー
e = c.copy()     # copy() メソッド
f = list(c)      # list() で作り直す
d.append(99)
print(c)         # [1, 2, 3](元は変わらない)

実機でも、b = aのあとb.append(4)するとa[1, 2, 3, 4]になりました。独立したコピーがほしいときは、c[:]c.copy()list(c)のいずれかを使います。さらに、もう1つ有名な罠があります。

multiply-trap.py
# NG: [[]]*3 は「同じ空リスト」を3つ並べる
grid = [[]] * 3
grid[0].append("X")
print(grid)   # [['X'], ['X'], ['X']] ← 全部に入ってしまう!

# OK: 内包表記で別々のリストを作る
grid = [[] for _ in range(3)]
grid[0].append("X")
print(grid)   # [['X'], [], []] ← 独立している

# 数値など変更できない値なら [0]*3 は問題ない
nums = [0] * 3   # [0, 0, 0](安全)
リストの掛け算は中身が共有される

[[]] * 3のように「リストを含むリスト」を掛け算で作ると、実機でも同じ内側リストが3つ並ぶ結果になりました。1つに追加すると、見かけ上すべてに入ります。2次元配列のような構造を作るときは、[[] for _ in range(3)]のように内包表記で1つずつ作ってください。一方、[0] * 3のように中身が数値(変更できない値)なら、共有されても書き換えで影響しないため問題ありません。

よくある失敗

extendのつもりでappendしてネストする

別のリストの中身を足したいならextendです。appendを使うとリストが丸ごと1要素として入り、入れ子になります。

b = a でコピーしたつもりになる

単純な代入は同じリストを指すだけです。独立したコピーはa[:]a.copy()list(a)で作ります。

[[]]*3 で2次元リストを作る

中身が共有されてしまいます。[[] for _ in range(3)]のように内包表記で1つずつ作ります。

new = lst.sort() と書く

sort()の戻り値はNoneです。新しいリストがほしいならsorted(lst)を使います。

remove / index で存在しない値を指定する

存在しない値をremoveindexに渡すとValueErrorになります。先にinで確認すると安全です。

よくある質問

Qappendとextendはどう使い分けますか?
A1個だけ追加するならappend、別のリストの中身をまとめて追加するならextendです。append([3, 4])はリストが1要素として入り[..., [3, 4]]になり、extend([3, 4])は中身が展開されて[..., 3, 4]になります。
Qリストをコピーするには?
Alst[:]lst.copy()list(lst)のいずれかを使います。単純なb = aはコピーではなく、同じリストを指すだけなので、片方を変えると両方変わります。
Qsortとsortedの違いは?
Asort()は元のリストを直接並び替え、戻り値はNoneです。sorted()は新しい並び替え済みリストを返し、元は変えません。元を残したいときや、戻り値を変数に入れたいときはsorted()を使います。
Q2次元リスト(リストのリスト)を作るには?
A[[] for _ in range(3)]のように内包表記で作ります。[[]] * 3は同じ内側リストを共有してしまい、1つに追加すると全部に入る罠があるため避けます。
Qリストの末尾を取り出して削除するには?
Alst.pop()を使います。末尾の要素を返しつつ、リストから取り除きます。位置を指定すればlst.pop(0)で先頭を取り出すこともできます。

まとめ

  • リストは[1, 2, 3]で作り、lst[0]lst[-1]・スライスlst[1:3]で取り出します。
  • 追加は1個ならappend、複数ならextendappendはリストごと1要素です。
  • 削除は値でremove、位置でpopdelです。
  • 並び替えは元を変えるsort()、新しく返すsorted()sort()の戻り値はNoneです。
  • コピーはlst[:]lst.copy()。単純な代入は同じリストを指します。
  • [[]]*3は中身が共有されるため、2次元は[[] for _ in range(3)]で作ります。

リストは、基本操作さえ押さえれば自在に扱えます。特に「appendextendの違い」「単純な代入はコピーではない」「[[]]*3の共有」の3つの罠を知っておけば、初心者がハマる落とし穴をほぼ回避できます。