Pythonで「値の集まり」を扱うとき、まずはリスト(list)を思い浮かべる方が多いと思います。
しかし、変更してほしくないデータこそタプル(tuple)の出番です。
本記事では、タプルの基本から操作、メリット、初心者がハマりやすい注意点までを丁寧に解説し、実践的なサンプルコードも交えて理解を深めます。
タプル(tuple)の基本
タプルは「変更できないリスト」(イミュータブル)
タプル(tuple)は作成後に要素の追加・変更・削除ができないイミュータブルなデータ構造です。
リストと似た見た目をしていますが、性質が異なります。
プログラム中で「うっかり書き換え」を防ぎたいときに役立ちます。
特に設定値や定数的なデータ、関数間の受け渡しなどで安全性が高まります。
リストとの違い(変更不可かどうか)
最大の違いは「変更できるかどうか」です。
リストはミュータブル(変更可能)、タプルはイミュータブル(変更不可)です。
記法にも違いがあります。
項目 | リスト(list) | タプル(tuple) |
---|---|---|
リテラル | [ ] | ( ) |
変更可否 | 変更できる | 変更できない |
代表的な用途 | 可変のコレクション、集計や編集 | 定数的データ、安全な受け渡し |
主な操作 | append、pop、sort など | count、index など(破壊的操作なし) |
辞書のキー | 不可 | 可(ハッシュ可能) |
違いをエラーで体感してみます。
タプルは要素代入ができません。
# リストは変更できる
lst = [1, 2, 3]
lst[0] = 99
print(lst) # [99, 2, 3]
# タプルは変更できない
t = (1, 2, 3)
# 次の行のコメントを外すとTypeErrorが発生します
# t[0] = 99
[99, 2, 3]
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment
タプルの作り方(()/tuple())
タプルは( )
またはtuple()
で作れます。
カンマがタプルの本質で、かっこは見やすさのために使われます。
# かっこを使う
t1 = (1, 2, 3)
# かっこ省略(カンマがあるのでタプルになる)
t2 = 1, 2, 3
# tuple() にイテラブルを渡す
t3 = tuple([1, 2, 3]) # リストから
t4 = tuple("abc") # 文字列から
t5 = tuple(range(3)) # range から
print(t1, t2, t3, t4, t5)
(1, 2, 3) (1, 2, 3) (1, 2, 3) ('a', 'b', 'c') (0, 1, 2)
空タプルと1要素タプル(, の注意)
1要素タプルは末尾のカンマが必須です。
空タプルは()
です。
empty = () # 空タプル
one1 = (1,) # 1要素タプル(カンマが必要)
one2 = 1, # かっこ省略でも可(カンマが必要)
not_tuple = (1) # これはタプルではなく、単なる1という数値
print(type(empty))
print(type(one1), one1)
print(type(one2), one2)
print(type(not_tuple), not_tuple)
<class 'tuple'>
<class 'tuple'> (1,)
<class 'tuple'> (1,)
<class 'int'> 1
型を調べる(type)
型が不安なときはtype()
で確認できます。
t = (10, 20, 30)
print(type(t))
<class 'tuple'>
タプルの基本操作(使い方)
要素を取得する(インデックス)
インデックスで要素にアクセスできます。
0始まりで、負のインデックスは後ろから数えます。
t = ('a', 'b', 'c', 'd')
print(t[0]) # 先頭
print(t[2]) # 3番目
print(t[-1]) # 末尾
print(t[-2]) # 後ろから2番目
a
c
d
c
一部を取り出す(スライス)
スライス[start:stop:step]
で部分取得できます。
新しいタプルが返ります。
t = (0, 1, 2, 3, 4, 5)
print(t[1:4]) # 1以上4未満
print(t[:3]) # 先頭から3未満
print(t[3:]) # 3以降
print(t[::2]) # 2刻み
print(t[::-1]) # 逆順
(1, 2, 3)
(0, 1, 2)
(3, 4, 5)
(0, 2, 4)
(5, 4, 3, 2, 1, 0)
含まれるか調べる(in)
in
演算子で要素の有無を確認できます。
t = ('apple', 'banana', 'cherry')
print('banana' in t)
print('grape' in t)
True
False
長さを調べる(len)
len()
で要素数がわかります。
t = (10, 20, 30, 40)
print(len(t))
4
要素の数と位置(count/index)
count()
は出現回数、index()
は最初の位置を返します。
t = ('a', 'b', 'a', 'c', 'a')
print(t.count('a')) # 'a' の個数
print(t.index('a')) # 'a' が最初に現れる位置
print(t.index('a', 1)) # 1以降で最初に現れる位置
3
0
2
連結と繰り返し(+ と *)
タプル同士の+
で連結、*
で繰り返しができます。
どちらも新しいタプルを返します。
a = (1, 2)
b = (3, 4)
print(a + b) # 連結
t = ('x',)
print(t * 3) # 繰り返し
(1, 2, 3, 4)
('x', 'x', 'x')
forで順番に処理する
タプルは反復可能なのでfor
で順に処理できます。
t = ('red', 'green', 'blue')
for color in t:
print(color)
# インデックスも使いたい場合は enumerate()
for i, color in enumerate(t):
print(i, color)
red
green
blue
0 red
1 green
2 blue
アンパック代入(複数の変数に展開)
タプルの形で左辺に並べると、一気に変数へ展開できます。
可読性が高まります。
# 基本のアンパック
t = (10, 20, 30)
a, b, c = t
print(a, b, c)
# 使わない値を _ に受ける慣習
_, second, _ = t
print(second)
# 可変長(アスタリスク)アンパック
head, *middle, tail = (1, 2, 3, 4, 5)
print(head, middle, tail)
10 20 30
20
1 [2, 3, 4] 5
タプルのメリットと使いどころ
変更させたくない設定や定数に
プログラム中で変えてはいけない値はタプルで表すと安全です。
例えば曜日や固定メニューなどです。
# 変更させたくない定数的なデータ
WEEKDAYS = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
# 誤って変更しようとするとエラーになるので安心
# WEEKDAYS[0] = 'Mond' # TypeError
print(WEEKDAYS)
('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
関数の戻り値で複数の値を返す
関数から複数の値をタプルで返し、呼び出し側でアンパックすると便利です。
def min_max_avg(numbers):
# 最小、最大、平均をタプルで返す
mn = min(numbers)
mx = max(numbers)
avg = sum(numbers) / len(numbers)
return mn, mx, avg # タプルで返る
data = [10, 20, 30, 40]
mn, mx, avg = min_max_avg(data)
print(mn, mx, avg)
10 40 25.0
辞書のキーにできる(ハッシュ可能)
タプルはハッシュ可能なので辞書のキーに使えます。
座標や複合キーなどで重宝します。
# 2次元座標をキーにして値を管理
grid = {}
grid[(0, 0)] = 'start'
grid[(1, 2)] = 'tree'
print(grid[(1, 2)])
# リストはキーにできない(ミュータブルでハッシュ不可)
try:
bad_key = [1, 2]
d = {bad_key: 'NG'}
except TypeError as e:
print('Error:', e)
tree
Error: unhashable type: 'list'
メモリ/速度で有利な場合がある
タプルはリストよりメモリ使用量が少ない傾向があり、特に「変更しない多数の要素」を扱うときに有利です。
速度面でも生成やアクセスがわずかに有利なケースがあります(環境によります)。
import sys
from timeit import timeit
lst = [0, 1, 2, 3, 4]
tup = (0, 1, 2, 3, 4)
print('list size:', sys.getsizeof(lst))
print('tuple size:', sys.getsizeof(tup))
# 生成コスト比較(環境で差は変わります)
t_list = timeit("[0,1,2,3,4]", number=1000000)
t_tuple = timeit("(0,1,2,3,4)", number=1000000)
print('make list :', t_list)
print('make tuple:', t_tuple)
list size: 104
tuple size: 80
make list : 0.13 # 例: 一例の計測値(環境で変動します)
make tuple: 0.09 # 例: 一例の計測値(環境で変動します)
計測値はマシンやPythonのバージョンで変動します。
傾向を見る参考程度にしてください。
初心者がハマりやすい注意点
1要素タプルはカンマを忘れない
1要素タプルは(値,)
のように必ずカンマが必要です。
(値)
は単なる括弧で、タプルではありません。
one = (42,) # OK: タプル
not_tuple = (42) # NG: タプルではない
print(type(one), one)
print(type(not_tuple), not_tuple)
<class 'tuple'> (42,)
<class 'int'> 42
()で囲んでもタプルとは限らない
かっこは「グルーピング」にも使われるので、タプルかどうかは「カンマがあるか」で決まります。
なお、カンマがあればかっこ省略でもタプルです。
a = (1 + 2) # 計算のグルーピング。結果は整数 3
b = 1, 2, 3 # カンマがあるのでタプル
c = (1, 2, 3) # もちろんタプル
print(type(a), a)
print(type(b), b)
print(type(c), c)
<class 'int'> 3
<class 'tuple'> (1, 2, 3)
<class 'tuple'> (1, 2, 3)
要素の追加・変更・削除はできない
タプルはappend
やremove
などの破壊的操作がありません。
代入や削除も不可です。
t = (1, 2, 3)
# 変更は不可
try:
t[0] = 99
except TypeError as e:
print('assign Error:', e)
# 追加メソッドは存在しない
try:
t.append(4) # AttributeError
except AttributeError as e:
print('append Error:', e)
# 削除も不可
try:
del t[1]
except TypeError as e:
print('delete Error:', e)
assign Error: 'tuple' object does not support item assignment
append Error: 'tuple' object has no attribute 'append'
delete Error: 'tuple' object doesn't support item deletion
補足として、タプルの中にリストなどのミュータブルな要素を入れると「タプル自体は同じまま、内部のリストは変更できる」点に注意してください。
これは「タプルは要素への参照が不変」であり、「参照先のオブジェクトの変更可否までは保証しない」ためです。
t = ([1, 2], 99)
t[0].append(3) # タプルの0番目はリスト。リスト自体は変更できる
print(t)
([1, 2, 3], 99)
並べ替えはsortedで新しく作る
タプルは並べ替えできないのでsorted()
で並べ替えたリストを作り、必要ならtuple()
でタプルに戻します。
t = (3, 1, 4, 1, 5)
# 昇順のリストを取得
sorted_list = sorted(t)
print(sorted_list, type(sorted_list))
# タプルに戻す
sorted_tuple = tuple(sorted_list)
print(sorted_tuple, type(sorted_tuple))
# 逆順で新しく作る
desc_tuple = tuple(sorted(t, reverse=True))
print(desc_tuple)
[1, 1, 3, 4, 5] <class 'list'>
(1, 1, 3, 4, 5) <class 'tuple'>
(5, 4, 3, 1, 1)
まとめ
タプル(tuple)は「変更できないリスト」として、安全にデータを保持したい場面で強力な選択肢です。
作成は( )
かtuple()
、1要素なら(値,)
を忘れないことが重要です。
インデックスやスライス、in
、len()
、count()
、index()
といった基本操作はリストと似ていますが、変更操作はできません。
辞書のキーにできることや、関数から複数値を返す用途、メモリ面の利点も覚えておくと良いでしょう。
初心者がハマりやすい点(1要素タプルのカンマ、かっこ=タプルとは限らない、並べ替えはsorted()
で新しく作る)を意識しながら、用途に応じてリストとタプルを使い分けてください。