この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:爽健
更新日時:2026-06-11 07:07:02

タイトル: Tuple (値のペア)
SEOタイトル: Python tuple (値のペア) 完全ガイド(unpacking / namedtuple / 型ヒント)

この記事の要点
  • tuple不変な順序付きシーケンス(1, 2, 3) / 1, 2, 3 どちらでも作れる
  • 1 要素は (1,) (カンマ必須)。空は ()
  • unpacking: a, b = 1, 2swap: a, b = b, a
  • 関数の複数戻り値として頻用。実体は tuple
  • namedtuple / typing.NamedTuple で名前付きフィールド付き不変レコードを表現

tuple とは

tuple は要素を順序付きで保持する Python の組み込み型で、作成後に変更できない (immutable) のが list との最大の違いです。

  • 不変: 要素の追加・削除・置換不可
  • 順序付き: index で取得可能
  • 異なる型を混在可: (1, 'a', [1,2])
  • ハッシュ可: 要素もハッシュ可なら辞書のキー / set の要素にできる
  • 軽量: list より少ないメモリで作れる

作成方法

# 丸括弧
t1 = (1, 2, 3)
t2 = ('a', 'b', 'c')
t3 = (1, 'two', 3.0, [4, 5])      # 混在 OK

# 括弧は省略可 (カンマで判定される)
t4 = 1, 2, 3                       # ✅ tuple

# 1 要素タプルは末尾カンマ必須
single = (1,)                      # ✅ tuple
not_tuple = (1)                    # ❌ ただの int (括弧は式の優先順位)

# 空タプル
empty = ()

# コンストラクタ
t5 = tuple([1, 2, 3])              # list から
t6 = tuple('abc')                  # → ('a', 'b', 'c')
t7 = tuple(range(5))               # → (0, 1, 2, 3, 4)

アクセスと不変性

t = (10, 20, 30, 40, 50)

t[0]        # 10
t[-1]       # 50
t[1:4]      # (20, 30, 40)
len(t)      # 5
30 in t     # True

# ❌ 不変なので変更不可
t[0] = 100  # TypeError: 'tuple' object does not support item assignment

# ⚠️ 要素自体が mutable なら、その内部は変更可能
t = (1, [2, 3])
t[1].append(4)   # OK → (1, [2, 3, 4])
# tuple そのものは [2, 3, 4] という list を指すまま (同一参照)

unpacking (分解代入)

# 基本
a, b, c = (1, 2, 3)
# a=1, b=2, c=3

# swap (一時変数なし)
a, b = b, a

# 関数の複数戻り値
def divmod_custom(x, y):
    return x // y, x % y       # tuple を返す

q, r = divmod_custom(10, 3)    # q=3, r=1

# 星付き unpacking (PEP 3132)
a, *rest = (1, 2, 3, 4)        # a=1, rest=[2, 3, 4]
first, *mid, last = (1, 2, 3, 4, 5)
# first=1, mid=[2, 3, 4], last=5

# ネストした unpacking
(a, b), c = (1, 2), 3          # a=1, b=2, c=3

# 受け取り側で要らない値は _
_, x, _ = ('skip', 100, 'skip')

list との違い (使い分け)

項目tuplelist
記法(1, 2, 3)[1, 2, 3]
変更不可可能
メモリ大 (拡張用バッファ持ち)
dict のキー / set 要素OK (要素もハッシュ可なら)NG
関数の戻り値慣習的に複数値で使う
主な用途固定レコード、座標、定数集合動的に変わるコレクション

Effective Python の指針: 変更しないなら tuple、変更するなら list。

namedtuple (名前付きフィールド)

tuple は index アクセスだと「2 番目は何だっけ?」となりがち。namedtuple は名前で参照できる軽量レコード型を作ります。

from collections import namedtuple

# クラス定義
Point = namedtuple('Point', ['x', 'y'])
# あるいは Point = namedtuple('Point', 'x y')

p = Point(10, 20)
p.x        # 10
p.y        # 20
p[0]       # 10 (tuple なので index アクセスも可)

# unpacking
x, y = p   # 普通の tuple として展開可能

# 不変
p.x = 100  # ❌ AttributeError

# _replace で新しいインスタンスを作る (immutable update)
p2 = p._replace(x=99)   # Point(x=99, y=20)

# _asdict で dict 化
p._asdict()   # {'x': 10, 'y': 20}

typing.NamedTuple (型ヒント付き)

from typing import NamedTuple

class User(NamedTuple):
    id: int
    name: str
    email: str = ''   # デフォルト値

u = User(1, 'taro')
u.id      # 1
u.name    # 'taro'

# クラス構文なのでメソッドも書ける
class Vector(NamedTuple):
    x: float
    y: float

    def length(self) -> float:
        return (self.x ** 2 + self.y ** 2) ** 0.5

Vector(3, 4).length()   # 5.0

型ヒント (PEP 484)

from typing import Tuple   # Python 3.8 以下
# Python 3.9+ なら組み込みの tuple をそのまま使える

# 固定長 tuple
def get_point() -> Tuple[int, int]:
    return (10, 20)

# Python 3.9+
def get_point2() -> tuple[int, int]:
    return (10, 20)

# 可変長 tuple (同じ型が任意個)
def get_ids() -> tuple[int, ...]:
    return (1, 2, 3, 4)

# 関数の戻り値が複数なら基本的に tuple
def stats(nums: list[int]) -> tuple[int, float, int, int]:
    return len(nums), sum(nums) / len(nums), min(nums), max(nums)

tuple をキーにする辞書

# 2 次元グリッドの状態管理
grid = {}
grid[(0, 0)] = 'start'
grid[(5, 3)] = 'goal'

# 複合キーでのキャッシュ
cache = {}
cache[(user_id, date)] = result

# list はキーにできない
grid[[0, 0]] = 'x'   # ❌ TypeError: unhashable type: 'list'

主要メソッド

t = (1, 2, 3, 2, 1)

t.count(2)    # 2 (要素 2 の個数)
t.index(3)    # 2 (要素 3 のインデックス)

# 連結 / 繰り返し (新しい tuple を返す)
(1, 2) + (3, 4)    # (1, 2, 3, 4)
(0,) * 5           # (0, 0, 0, 0, 0)

# 反復
for v in t:
    print(v)

# enumerate との組み合わせ
for i, v in enumerate(['a', 'b', 'c']):
    # (i, v) が tuple
    print(i, v)

FAQ

Q: tuple は list より速い?
A: 作成・反復で僅かに速いことが多いです。ただし主な理由は「変わらない」ことを表現できる安全性です。

Q: 1 要素 tuple の (1,) が違和感ある
A: 必要なら tuple([1]) でも作れます。ただし慣習的に (1,) が定番。

Q: dataclass と namedtuple、どちらを使う?
A: 不変かつ軽量なら namedtuple、変更可能 or デフォルト値の多いレコードなら @dataclass (Python 3.7+)。