Pythonには、複数の値をまとめる入れ物としてリスト(list)のほかに、タプル(tuple)と集合(set)があります。タプルは「あとから変更できないリスト」、集合は「重複のない値の集まり」だと考えると分かりやすいです。座標や複数の戻り値はタプル、重複の除去やメンバー判定は集合、というように使い分けます。
つまずきやすいのは、要素が1個のタプルは末尾にカンマが必要((1,))という点と、空の集合はset()で作る({}は辞書になる)という点です。この記事では、実機のPythonで確認しながら、タプルと集合の使い方を整理します。
- タプルは
(1, 2, 3)で作る、変更できない並びです。 - 要素1個のタプルは
(1,)とカンマを付けます((1)はただの数値)。 a, b = (1, 2)のようにアンパックで複数の変数へ一度に代入できます。- 集合は
{1, 2, 3}で作る、重複のない集まりです。順序はありません。 - 空の集合は
set()で作ります。{}は辞書(dict)になります。 - 集合は和
|・積&・差-の演算や、高速なin判定が得意です。
変更できるリストはリスト(list)、キーと値で持つなら辞書(dict)、集合は内包表記と組み合わせると便利です。あわせて参考にしてください。
タプル(tuple)の基本
タプルは丸かっこ()で作ります。リストと同じく[0]で要素を取り出したり、スライスしたりできますが、あとから中身を変更できないのが大きな違いです。
t = (1, 2, 3) print(t) # (1, 2, 3) print(t[0]) # 1(インデックスで取り出す) print(t[-1]) # 3 print(t[0:2]) # (1, 2)(スライスもできる) print(len(t)) # 3 # かっこは省略できる(カンマがあればタプル) point = 10, 20 print(point) # (10, 20)
実機でも、t[0]で1、スライスt[0:2]で(1, 2)が取り出せました。取り出し方はリストと同じです。point = 10, 20のようにかっこを省略しても、カンマがあればタプルになります。
要素1個のタプルはカンマが必要
ここはよく間違える点です。要素が1個のタプルを作るときは、末尾にカンマを付けて(1,)と書きます。カンマがない(1)は、かっこで囲んだだけの「ただの数値」になってしまいます。
a = (1) # これはタプルではない(ただの int) b = (1,) # これがタプル(末尾にカンマ) print(type(a)) # <class 'int'> print(type(b)) # <class 'tuple'> print(b) # (1,)
実機で確認したところ、(1)の型はint、(1,)の型はtupleでした。かっこはタプルの目印ではなく、カンマがタプルの目印です。要素が1個のタプルを作りたいのにカンマを忘れると、タプルにならずにあとの処理でエラーになることがあります。1個のときは必ず(1,)と書きましょう。
タプルは変更できない(immutable)
タプルはイミュータブル(変更不可)です。要素を後から書き換えたり、追加・削除したりはできません。試みるとTypeErrorになります。
t = (1, 2, 3) # 要素を変更しようとするとエラー t[0] = 99 # TypeError: 'tuple' object does not support item assignment # 変更したいときは、いったんリストにする lst = list(t) # [1, 2, 3] lst[0] = 99 t = tuple(lst) # (99, 2, 3) に作り直す print(t)
実機でも、t[0] = 99とするとTypeError: 'tuple' object does not support item assignmentになりました。中身を変えたい場合は、list(t)でリストに変換してから書き換え、必要ならtuple()でタプルに戻します。「変更されたくないデータ」をタプルにしておくと、うっかり書き換えるミスを防げます。
タプルのアンパックと複数の戻り値
タプルはアンパックと相性が良く、複数の変数へ一度に代入できます。関数で複数の値を返すときも、実体はタプルです。
# アンパック(左辺の変数へ一度に代入)
a, b, c = (1, 2, 3)
print(a, b, c) # 1 2 3
# 値の入れ替えも一行で書ける
x, y = 10, 20
x, y = y, x
print(x, y) # 20 10
# 関数の「複数の戻り値」は実はタプル
def minmax(numbers):
return min(numbers), max(numbers)
result = minmax([3, 1, 2])
print(result) # (1, 3)
low, high = minmax([3, 1, 2]) # 受け取りもアンパック
print(low, high) # 1 3
実機でも、minmax([3,1,2])の戻り値は(1, 3)というタプルでした。low, high = minmax(...)のようにアンパックで受け取れます。x, y = y, xと書くだけで2つの変数の値を入れ替えられるのも、タプルのアンパックの便利な使い方です。
集合(set)の基本と重複除去
集合は波かっこ{}で作る、重複のない値の集まりです。同じ値を入れても1つにまとめられます。リストから重複を取り除きたいときによく使います。
s = {3, 1, 2, 2, 1}
print(s) # {1, 2, 3}(重複は除かれる・順序は保証されない)
# リストの重複を取り除く定番の方法
nums = [1, 1, 2, 3, 3, 3]
unique = list(set(nums))
print(unique) # [1, 2, 3]
実機でも、{3, 1, 2, 2, 1}は{1, 2, 3}になり、重複が除かれました。list(set(nums))はリストの重複除去の定番です。ただし集合には順序がありません。元の並び順を保ちたい場合は、別の方法(dict.fromkeysなど)を使います。
空の集合はset()({}は辞書)
もう1つの注意点です。空の集合を作りたいとき、{}と書くと空の辞書(dict)になってしまいます。空の集合はset()で作ります。
empty_dict = {} # これは空の辞書(dict)
empty_set = set() # これが空の集合(set)
print(type(empty_dict)) # <class 'dict'>
print(type(empty_set)) # <class 'set'>
実機で確認したところ、{}の型はdict、set()の型はsetでした。波かっこ{}は辞書と集合のどちらにも使う記号ですが、空のときは辞書が優先されます。{1, 2}のように要素があれば集合になりますが、空の集合がほしいときは必ずset()と書いてください。
集合の演算(和・積・差)
集合は、数学の集合と同じように和集合・積集合・差集合を計算できます。2つのデータの共通点や違いを調べるのに便利です。
A = {1, 2, 3}
B = {2, 3, 4}
print(A | B) # {1, 2, 3, 4} 和集合(どちらかにある)
print(A & B) # {2, 3} 積集合(両方にある)
print(A - B) # {1} 差集合(Aにだけある)
print(A ^ B) # {1, 4} 対称差(どちらか片方だけにある)
# メソッドでも書ける
print(A.union(B)) # {1, 2, 3, 4}
print(A.intersection(B)) # {2, 3}
実機でも、A | Bは{1, 2, 3, 4}、A & Bは{2, 3}、A - Bは{1}になりました。「両方のリストに共通する要素」を求めたいときは積集合&、「片方にしかない要素」は差集合-が便利です。記号のほか、union()・intersection()といったメソッドでも同じことができます。
要素の追加・削除とin判定
集合にはadd()で要素を追加、discard()やremove()で削除します。また、ある値が含まれるかのin判定が、リストより高速なのも集合の特長です。
s = {1, 2, 3}
s.add(5) # 追加 → {1, 2, 3, 5}
s.discard(1) # 削除 → {2, 3, 5}(無くてもエラーにならない)
# s.remove(9) # remove は無いとエラー(KeyError)
print(s) # {2, 3, 5}
# in 判定(集合は高速)
print(2 in s) # True
print(9 in s) # False
「この値はリストの中にあるか?」という判定(in)を何度も行う場合、リストよりも集合のほうが高速です。リストは先頭から順に探すのに対し、集合は仕組み上ほぼ一定の速さで判定できるためです。大量のデータに対して何度も含まれるかを確認するなら、いったんset()に変換してからinで調べると効率的です。なおdiscard()は要素が無くてもエラーになりませんが、remove()は無いとKeyErrorになる点が違います。
リスト・辞書との使い分け
4つの入れ物の特徴をまとめます。目的に合わせて選びます。
| 種類 | 書き方 | 特徴・主な用途 |
|---|---|---|
| リスト list | [1, 2, 3] |
順序あり・変更できる。並びを扱う基本 |
| タプル tuple | (1, 2, 3) |
順序あり・変更できない。座標・複数の戻り値 |
| 集合 set | {1, 2, 3} |
重複なし・順序なし。重複除去・集合演算・in判定 |
| 辞書 dict | {"a": 1} |
キーと値の対応。名前で値を引く |
「変更したくない並び」はタプル、「重複をなくしたい・共通点を調べたい」は集合、「キーで値を引きたい」は辞書、それ以外の基本はリスト、と考えると選びやすくなります。
よくある失敗
要素1個のタプルでカンマを忘れる
(1)はただの数値です。1個のタプルは(1,)とカンマを付けます。
空の集合を{}で作ってしまう
{}は空の辞書です。空の集合はset()で作ります。
タプルの要素を書き換えようとする
タプルは変更できません。t[0] = xはエラーです。変更したいときはlist()に変換します。
集合に順序を期待する
集合には順序がありません。set[0]のようなインデックス指定もできません。順序が必要ならリストを使います。
remove()で無い要素を消そうとする
remove()は無い要素を指定するとKeyErrorになります。エラーにしたくないときはdiscard()を使います。
よくある質問
(x, y)のような「セットで意味を持つ変わらないデータ」や、関数の複数の戻り値に向いています。リストは要素の追加・削除・並べ替えができる、並びを扱う基本の入れ物です。(1,)と書きます。(1)はかっこで囲んだだけの数値になってしまいます。タプルの目印はかっこではなくカンマです。list(set(リスト))が簡単です。ただし集合には順序が無いため、元の並び順が保証されません。順序を保ったまま重複を消したいときはlist(dict.fromkeys(リスト))を使います。set()で作ります。{}は空の辞書(dict)になるため、空の集合には使えません。要素がある場合は{1, 2, 3}で集合になります。set(リストA) & set(リストB)で、両方に含まれる要素が得られます。片方にしかない要素は差集合set(A) - set(B)で求められます。まとめ
- タプルは
(1, 2, 3)で作る変更できない並び。1個のときは(1,)。 - タプルはアンパック(
a, b = t)や複数の戻り値で活躍します。 - 集合は
{1, 2, 3}で作る重複なしの集まり。list(set(...))で重複除去。 - 空の集合は
set()。{}は辞書になります。 - 集合は和
|・積&・差-の演算と、高速なin判定が得意です。 - 変更不可ならタプル、重複除去・集合演算なら集合、と使い分けます。
タプルと集合は、リストや辞書と並ぶPythonの基本データ型です。「変更させたくないからタプル」「重複をなくしたいから集合」と、目的に合わせて選べるようになると、コードがぐっと読みやすく・安全になります。

