タプルのアンパッキング(複数の変数へ一度に代入するテクニック)は、Pythonコードを短く読みやすくする強力な文法です。
本記事では、基本から注意点、そして日常で使える実例10選まで、初心者の方にも分かりやすく丁寧に解説します。
読み終えるころには自然に使いこなせるはずです。
タプルのアンパッキングとは?
意味とメリット
タプルのアンパッキングとは、並んだ値を並んだ変数へ一度に割り当てる代入方法のことです。
Pythonではこのスタイルを使うことで、コードが簡潔になり、意図も明確になります。
例えば、従来は変数に順番に代入していた処理が、アンパッキングなら1行で表現できます。
さらに可読性が高まる、バグの混入を減らせるといった実利も大きいため、Pythonでのコーディング効率化に直結します。
なお「タプルのアンパッキング」と呼ばれますが、実際にはタプル以外のイテラブル(シーケンス)にも使えます。
基本の書き方
いちばん基本の形は、左辺に変数を並べ、右辺に値を並べる
というものです。
かっこは省略可能で、右辺がタプルでなくても同じ長さのシーケンスであれば代入できます。
# 基本形の例1: タプルをほどいて2つの変数に代入
a, b = (10, 20)
print(a, b) # 10 20
# 基本形の例2: 右辺の()は省略できる
x, y, z = 1, 2, 3
print(x, y, z) # 1 2 3
# 基本形の例3: リストでもOK(シーケンスであればよい)
r, g, b = [255, 128, 64]
print(r, g, b) # 255 128 64
10 20
1 2 3
255 128 64
左右の要素数が一致していることが基本ルールです。
詳細は後述の注意点を参照してください。
タプル以外のシーケンスにも使える
アンパッキングはlist
やstr
、range
、zip
などのイテラブルにも使えます。
文字列は1文字ずつに分解されるため、短いケースに限り便利です。
長すぎる場合はエラーや過剰な代入になるため注意しましょう。
以下は対応の一例です。
対象 | 例 | 補足 |
---|---|---|
タプル(tuple) | a, b = (1, 2) | もっとも基本 |
リスト(list) | x, y = [10, 20] | シーケンスならOK |
文字列(str) | c1, c2 = "Hi" | 文字ごとに分解 |
range | p, q, r = range(3) | 0,1,2を受け取る |
zipの結果 | for a, b in zip(L1, L2) | 2要素タプルを展開 |
enumerateの結果 | for i, v in enumerate(L) | (index, value) |
dict.items | for k, v in d.items() | (key, value) |
ジェネレータ | a, b, c = gen() | イテラブルなら可能だが消費に注意 |
実例を見てみます。
# 文字列のアンパッキング
c1, c2 = "OK"
print(c1, c2) # O K
# rangeで3要素を受け取る
u, v, w = range(3)
print(u, v, w) # 0 1 2
# zipをforループで展開する
for left, right in zip([1, 2], ["a", "b"]):
print(left, right)
O K
0 1 2
1 a
2 b
イテラブルの長さと左辺の変数数の整合性が重要です。
合わない場合はエラーになるため、次章の*
付きアンパッキングを活用しましょう。
タプルのアンパッキングの使い方と注意点
要素数は左右をそろえる
基本のアンパッキングでは、左辺の変数数と右辺の要素数が一致している必要があります。
一致しない場合、ValueErrorが発生します。
# 要素が3つあるのに、左辺が2つしかない
a, b = [1, 2, 3] # これはエラー
Traceback (most recent call last):
...
ValueError: too many values to unpack (expected 2)
修正するには、*
付きアンパッキングで残りをまとめるか、値の数を合わせるようにしましょう。
*付きアンパッキングで残りをまとめる
Python 3では、を付けた変数に「残りの要素」をまとめて受け取れます(PEP 3132)。
この変数には必ずリストが入ります。
左辺にを使えるのは1つだけです。
# 先頭と残りを受け取る
first, *rest = [10, 20, 30, 40]
print(first) # 10
print(rest) # [20, 30, 40]
# 先頭・末尾を取りつつ、中間はまとめて受け取る
head, *middle, tail = (1, 2, 3, 4, 5)
print(head, middle, tail) # 1 [2, 3, 4] 5
# 要素が少なくても動く(空リストになる)
x, *xs = [99]
print(x, xs) # 99 []
10
[20, 30, 40]
1 [2, 3, 4] 5
99 []
不要な値は_で捨てる
使わない値はアンダースコア_
に代入して捨てるのが慣習です(PEP 8でも示唆)。
複数捨てるときは_
を繰り返しても構いませんが、読みやすさのために_, _
程度に留めましょう。
# 2つめの値は使わない
user_id, _ = (42, "ignore")
print(user_id) # 42
# 先頭だけ使い、残りは捨てる
first, *_ = [1, 2, 3, 4]
print(first) # 1
42
1
「捨てる」という意思表示ができ、読み手に優しいコードになります。
ネストしたタプルをほどく
アンパッキングは入れ子の構造にも使えます。
左辺の構造を右辺の構造に合わせるのがコツです。
# ネストした構造を1度に展開する
(x, (y1, y2)) = (10, (20, 30))
print(x, y1, y2) # 10 20 30
# forループでのネスト展開
pairs = [(1, (2, 3)), (4, (5, 6))]
for a, (b, c) in pairs:
print(a, b, c)
10 20 30
1 2 3
4 5 6
つまずきやすいエラー例
初心者が遭遇しやすいエラーと対処をまとめます。
# 1) 数が合わない
a, b = [1, 2, 3] # ValueError
# 2) *を2つ以上使う(左辺) -> 構文エラー
*a, *b, c = [1, 2, 3, 4] # SyntaxError
# 3) アンパックできない値(非イテラブル) -> 型エラー
x, y = 10 # TypeError
# 4) dictをそのままアンパック -> キーのみが対象
d = {"k1": 1, "k2": 2}
k1, k2 = d # 'k1', 'k2'が入る。値は入らない点に注意
Traceback (most recent call last):
...
ValueError: too many values to unpack (expected 2)
File "<stdin>", line 2
SyntaxError: two starred expressions in assignment
Traceback (most recent call last):
...
TypeError: cannot unpack non-iterable int object
「数を合わせる」「*
は1つ」「右辺はイテラブル」の3点を覚えておけば、ほとんどのエラーを避けられます。
タプルのアンパッキング 実例10選
同時代入で変数を初期化する
複数の初期値を1行で代入できます。
意図が一目で分かり、後から読む人にも優しい書き方です。
# 3つの変数を同時に初期化
width, height, depth = 1920, 1080, 32
print(width, height, depth)
# 同じ値を代入したい場合のイディオム
x = y = z = 0 # これはアンパッキングではないが、初期化でよく使う
print(x, y, z)
1920 1080 32
0 0 0
値の入れ替えを1行で行う
一時変数なしでスワップできます。
Pythonらしい書き方で、もっとも有名なユースケースです。
a, b = 1, 2
a, b = b, a # 入れ替え
print(a, b) # 2 1
2 1
一時変数を使うより安全で短いため、バグの混入を減らせます。
関数の複数戻り値を受け取る
関数がタプルを返せば、呼び出し側は自然に分解して受け取れます。
def bbox(points):
"""与えられた2D座標群から、(min_x, min_y, max_x, max_y)を返す"""
xs = [x for x, _ in points]
ys = [y for _, y in points]
return min(xs), min(ys), max(xs), max(ys) # タプル(のように)返す
pts = [(1, 2), (3, 0), (5, 4)]
min_x, min_y, max_x, max_y = bbox(pts) # 4変数に展開
print(min_x, min_y, max_x, max_y)
1 0 5 4
戻り値の意味が変数名で明確になるため、コメントを減らしても意図が伝わります。
divmodで商と余りを受け取る
divmod(a, b)
は(商, 余り)
を返します。
整数計算で頻出です。
q, r = divmod(23, 5)
print(q, r) # 商4、余り3
4 3
os.path.splitextで名前と拡張子を分ける
ファイル名処理の定番です。
拡張子にはドット込みで入る点に注意します。
import os
filename, ext = os.path.splitext("report_2025-09.csv")
print(filename) # report_2025-09
print(ext) # .csv
report_2025-09
.csv
forループで座標(x, y)を展開する
2次元座標のリストを処理する際に読みやすく書けます。
points = [(0, 0), (1, 2), (2, 4)]
for x, y in points: # (x, y)を同時に展開
print(f"({x}, {y})")
(0, 0)
(1, 2)
(2, 4)
enumerateの(インデックス, 値)を展開する
enumerate
は(index, value)
のペアを返すので、アンパッキングで扱いやすくなります。
names = ["Alice", "Bob", "Carol"]
for i, name in enumerate(names, start=1):
print(i, name)
1 Alice
2 Bob
3 Carol
dict.itemsの(キー, 値)を展開する
辞書の項目をキーと値に分けるのは非常に一般的です。
右辺の構造が明確なので可読性が高いです。
config = {"host": "localhost", "port": 5432}
for key, value in config.items():
print(f"{key} = {value}")
host = localhost
port = 5432
zipで複数リストを同時にループする
複数のリストをペアにし、1回のループで処理できます。
ids = [101, 102, 103]
scores = [88, 92, 77]
for sid, score in zip(ids, scores):
print(sid, score)
101 88
102 92
103 77
長さが異なる場合は短い方に揃う点に注意してください。
先頭・中間・末尾を取り出す(first, *middle, last)
先頭と末尾を取りつつ、中間をまとめて処理できる便利なイディオムです。
data = [10, 20, 30, 40, 50]
first, *middle, last = data
print(first) # 10
print(middle) # [20, 30, 40]
print(last) # 50
10
[20, 30, 40]
50
よくある質問(初心者向け)
要素数が合わない時の対処は?
基本は*
付きアンパッキングを使うのが簡単で安全です。
例えばa, *rest = seq
やhead, _, tail = seq
のように書けば、短いケースから長いケースまで対応できます。
必ず1つだけを使う点に注意してください。
どうしても個数が固定で扱いたいなら、事前にlen(seq)
を確認したり、スライスで明示的に切り出してから代入するのも有効です。
タプルとリストの違いと使い分けは?
タプルは不変(immutable)、リストは可変(mutable)です。
どちらもアンパッキングできますが、意味づけが異なります。
変わらない固定の組(例えば(x, y)
座標や設定の組)にはタプル、後で追加・変更・削除するコレクションにはリストが適します。
観点 | タプル(tuple) | リスト(list) |
---|---|---|
可変性 | 変更不可 | 変更可能 |
代表的用途 | 不変のレコード、関数の複数戻り値 | 順序ある可変の集合 |
速度・メモリ | やや軽量 | やや重め(機能が多い) |
アンパッキング | 可能 | 可能 |
「変えないもの=タプル」「変える可能性があるもの=リスト」を目安に使い分けるとよいでしょう。
*を使う時の読みやすさのコツは?
- 役割が伝わる名前にする:
first, *middle, last
やhead, *tail
のように慣用的な語彙を使うと意図が伝わります。 - 捨てるなら
_
:head, *_, tail
のように、不要な値は_
で明示します。 *
は1つだけ: 左辺に複数置くとSyntaxErrorになります。- 極端に長い右辺は避ける: 可読性が落ちる場合は、一旦変数に入れる、スライスするなど段階的に書くと見やすくなります。
まとめ
タプルのアンパッキングは、Pythonの可読性と生産性を大きく上げる基礎テクニックです。
基本は「左右の数を合わせる」こと、柔軟に扱いたいときは「*
付きアンパッキング」を使うこと、不要な値は「_
で捨てる」ことを押さえれば、実務でも迷いなく使えます。
タプルだけでなくリストや文字列、zip
やenumerate
の結果にも適用でき、関数の複数戻り値やスワップ、ループ処理の明確化など、実例で見た通り活躍の幅は広いです。
今日から少しずつ導入して、コードを短く読みやすくしていきましょう。