Pythonでタプルやリストをアンパック(複数の変数に展開して代入)

Pythonでは、タプルやリストの要素を展開して複数の変数に代入することができます。シーケンスのアンパック (sequence unpacking) やアンパック代入などと呼ばれる。

  1. データ構造 タプルとシーケンス — Python 3.7.0 ドキュメント

ここでは以下の内容について説明します。

タプル、リストのアンパックの基本 ネストした(入れ子になった)タプル、リストのアンパック アンダースコア_を使ったアンパック アスタリスク*を使ったアンパック

タプルやリスト、辞書を関数の引数に展開して渡す場合については

タプル、リストのアンパックの基本

左辺に変数をカンマ,で区切って書くと、それぞれの変数に右辺のタプルやリストの要素が代入されます。タプルでもリストでも同じ(以降の例はタプルで記述)。

t = (0, 1, 2)

a, b, c = t

print(a)
print(b)
print(c)
# 0
# 1
# 2

l = [0, 1, 2]

a, b, c = l

print(a)
print(b)
print(c)
# 0
# 1
# 2

なお、タプルは丸括弧を省略可能であるため、これを利用して以下のように複数の変数に複数の値を1行で代入することができます。

a, b = 0, 1

print(a)
print(b)
# 0
# 1

変数の数と要素の数が一致していないとエラーになります。

# a, b = t
# ValueError: too many values to unpack (expected 2)

# a, b, c, d = t
# ValueError: not enough values to unpack (expected 4, got 3)

なお、変数の数が要素の数より少ない場合は、変数名にアスタリスク*をつけて残りの要素をリストとして代入することが可能(後述)。

ネストした(入れ子になった)タプル、リストのアンパック

ネストした(入れ子になった)タプル、リストもアンパックできます。中身も展開したい場合は変数を()または[]で囲む。

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

a, b, c = t

print(a)
print(b)
print(c)
# 0
# 1
# (2, 3, 4)

print(type(c))
# <class 'tuple'>

a, b, (c, d, e) = t

print(a)
print(b)
print(c)
print(d)
print(e)
# 0
# 1
# 2
# 3
# 4

アンダースコア_を使ったアンパック

アンパックに限らず、Pythonでは必要のない値は慣例的にアンダースコア(アンダーバー)_に代入することがあります。文法的に特別な意味があるわけではなく、単に_という名前の変数に代入されているだけです。

t = (0, 1, 2)

a, b, _ = t

print(a)
print(b)
print(_)
# 0
# 1
# 2

アスタリスク*を使ったアンパック

変数の数が要素の数よりも少ない場合、変数名にアスタリスク*をつけると、要素がリストとしてまとめて代入されます。 この文法はPython3から実装されたもので、Python2では使えない。 がついていない変数に先頭と末尾から要素が代入され、残りの要素がリストとしてがついた変数に代入されます。

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

a, b, *c = t

print(a)
print(b)
print(c)
# 0
# 1
# [2, 3, 4]

print(type(c))
# <class 'list'>

a, *b, c = t

print(a)
print(b)
print(c)
# 0
# [1, 2, 3]
# 4

*a, b, c = t

print(a)
print(b)
print(c)
# [0, 1, 2]
# 3
# 4

例えば、タプルやリストの先頭の2つの要素だけ変数に代入したいときは、必要のない部分に対して上述のアンダースコア_を使う場合があります。

a, b, *_ = t

print(a)
print(b)
print(_)
# 0
# 1
# [2, 3, 4]

同じことは以下のようにも書けます。

a, b = t[0], t[1]

print(a)
print(b)
# 0
# 1

*がつけられるのは一つだけです。*がついた変数が複数あると要素を何個ずつ振り分けるか判断できないのでエラーSyntaxErrorになります。

# *a, b, *c = t
# SyntaxError: two starred expressions in assignment

*がついた変数に代入される要素が一つだけでもリストとして代入されるので気をつけてください。

t = (0, 1, 2)

a, b, *c = t

print(a)
print(b)
print(c)
# 0
# 1
# [2]

print(type(c))
# <class 'list'>

余分の要素がない場合は空のリストが代入されます。

a, b, c, *d = t

print(a)
print(b)
print(c)
print(d)
# 0
# 1
# 2
# []
Last Updated: 6/26/2019, 10:34:03 PM