Python | データ構造強化:タプルのアンパック

Python Python
スポンサーリンク

概要(タプルのアンパックは「並んだ値を並んだ変数へ一度に割り当てる」)

タプルのアンパックは、複数の値を一度に複数の変数へ代入する文法です。インデックスを使わず「意味のある名前」に直で割り当てられるので、コードが短く、意図が明確になります。基本の同数アンパック、余りをまとめる“拡張アンパック()”、不要要素の捨て方(_)、入れ子構造のアンパック、関数引数への展開(args, **kwargs)まで押さえると、日常の処理が驚くほど綺麗に書けます。

基本の使い方(ここが重要)

同数アンパック(値の数=変数の数)

point = (10, 20)
x, y = point
print(x, y)  # 10 20
Python

左右の要素数が一致しないと ValueError になります。まずは「数を揃える」が鉄則です。

x, y = (10,)        # ValueError: not enough values to unpack
a, b = (1, 2, 3)    # ValueError: too many values to unpack
Python

拡張アンパック(*で「残り」をひとまとめ)

「余りを全部まとめて受けたい」なら、変数の前に * を置きます。まとまった値はリストになります。

a, *rest = (1, 2, 3, 4)
print(a, rest)      # 1 [2, 3, 4]

*a, b = (1, 2, 3, 4)
print(a, b)         # [1, 2, 3] 4

first, *middle, last = (1, 2, 3, 4, 5)
print(first, middle, last)  # 1 [2, 3, 4] 5
Python

“*は1つだけ”がルールです(左右に複数置くことはできません)。

不要な値は「_」で捨てる(読みやすさ重視)

使わない値には、慣習的に _ を使うと意図が伝わります。

x, _ = (10, 20)                # 2つ目は使わない
_, _, z = (1, 2, 3)            # zだけ欲しい
first, *_, last = range(10)    # 途中は捨てて両端だけ
Python

入れ子と実務での定番パターン

入れ子のアンパック(形を合わせる)

タプルの中にタプルがあるなら、左辺も同じ形にします。

record = ("alice", (25, "Tokyo"))
name, (age, city) = record
Python

値の入れ替え(swap)を1行で

一時変数なしで安全に入れ替えられます。

a, b = 1, 2
a, b = b, a
Python

関数の複数戻り値を受け取る

戻り値をタプルで返す設計にして、自然に展開します。

def stats(xs):
    return min(xs), max(xs), sum(xs)/len(xs)

m, M, avg = stats([1, 2, 3, 4])
Python

ループでのアンパック(ペア・座標・辞書 items)

pairs = [("A", 10), ("B", 20)]
for label, value in pairs:
    print(label, value)

points = [(1, 2), (3, 4)]
for x, y in points:
    print(x + y)

d = {"id": 101, "name": "alice"}
for key, val in d.items():
    print(key, val)
Python

関数引数への展開(* と ** を正しく使う)

可変引数へ展開(*args)

「引数の列」をそのまま渡したいときに使います。数が一致していないと呼び出し側でエラーになる点は同じです。

def add(a, b, c):
    return a + b + c

vals = (1, 2, 3)
print(add(*vals))  # 6
Python

キーワード引数へ展開(**kwargs)

辞書を「キー名で」展開して渡します。関数側のパラメータ名と辞書キーが一致している必要があります。

def create_user(id, name, city="Tokyo"):
    return {"id": id, "name": name, "city": city}

data = {"id": 101, "name": "alice"}
print(create_user(**data))
Python

重要ポイントの深掘り(安全性・エラー・応用設計)

要素数の整合性が最重要(テストで守る)

アンパックは「形が合っている」ことが前提です。不定長データには拡張アンパックを使うか、事前に長さをチェックして安全に扱います。

def head_tail(xs):
    if len(xs) < 2:
        raise ValueError("少なくとも2要素が必要です")
    first, *_, last = xs
    return first, last
Python

拡張アンパックは「1箇所だけ」。結果はリスト

拡張アンパックの結果はリスト(タプルではない)になります。型を揃えたいなら必要に応じて tuple(…) に変換します。

first, *middle, last = (1, 2, 3)
middle = tuple(middle)  # 必要ならタプルへ
Python

位置引数とキーワード引数の組み合わせ

展開は位置()→キーワード(*)の順で書きます。順序を逆にすると構文エラーです。

def f(a, b, c, d=0):
    ...

args = (1, 2)
kwargs = {"c": 3, "d": 4}
f(*args, **kwargs)    # OK
# f(**kwargs, *args)  # SyntaxError
Python

可読性を最優先(過度なアンパックは分割する)

ネストや * の位置が複雑になるほど読みづらくなります。途中変数に分けるだけで保守性が大きく向上します。

record = ("alice", (25, "Tokyo"), [1, 2, 3])

name, rest = record[0], record[1:]
age, city = rest[0]
nums = rest[1]
Python

例題で身につける(定番から一歩先まで)

例題1:ファイル名と拡張子を分解

import os
fname = "report_2025-12-15.csv"
base, ext = os.path.splitext(fname)
print(base, ext)  # report_2025-12-15 .csv
Python

例題2:自然な並びでヘッダ付き行を展開

row = ("alice", 85, 25)
name, score, age = row
print(f"{name} scored {score} ({age}y)")
Python

例題3:先頭・中間・末尾だけ取り出す

seq = [10, 20, 30, 40, 50]
first, *middle, last = seq
print(first, middle, last)  # 10 [20, 30, 40] 50
Python

例題4:zip+アンパックで列へ戻す(unzip)

pairs = [("A", 1), ("B", 2), ("C", 3)]
labels, values = zip(*pairs)
print(labels, values)  # ('A','B','C') (1,2,3)
Python

例題5:divmod の複数戻り値

q, r = divmod(17, 5)
print(q, r)  # 3 2
Python

例題6:for で座標を展開しつつ処理

points = [(1, 2), (3, 4), (5, 6)]
for x, y in points:
    print(x * y)
Python

まとめ

タプルのアンパックは「並んだ値を、意味のある変数名へまとめて割り当てる」ための基本技です。要素数の整合を守り、足りない/多い場合は拡張アンパック(*)や事前チェックで安全に扱う。不必要な値は _ で捨て、入れ子は形を合わせてほどく。関数引数では * と ** を適切に使い分ける。過度に凝らず、読みやすさを最優先すると、日々の処理が短く、明快で、堅牢になります。

タイトルとURLをコピーしました