【Python】リスト・タプル・辞書:一度に要素を複数の変数に代入(アンパック)

2021.11.07 /

【Python】リスト・タプル・辞書:一度に要素を複数の変数に代入(アンパック)

本記事ではPythonのデータ型(リスト・タプル・辞書)を分解して、一度に要素を複数の変数に代入する方法を解説していきます。

1つの代入文でリストなどを分解して、要素を各変数に代入することをアンパック代入と呼びます。

アンパックを利用することで、インデックスで要素にアクセスするよりも見た目がきれいになり、コードの行数を少なくできます。

ぜひアンパックをマスターして、すっきりした読みやすいコードを書けるようにしましょう。

アンパック

アンパック代入とは

アンパック代入とは、1つの代入文でリストやタプルなどに格納されている複数要素を複数の変数に代入することです。

変数はリストやタプルに格納されている要素の数だけ用意する必要があります。

アンパックを利用するメリットは次のようなものがあります。

  • 各要素にインデックスでアクセス不要
  • コードの行数が減りすっきりする

アンパックの使用方法

アンパックでは左辺に要素と同じ数の変数を列挙し、右辺にリストやタプルを指定します。

構文

変数1, 変数2, …, 変数N = [要素1, 要素2, …, 要素N]

# リストの場合
data = [4,5,54]
a, b, c = data
print(a, b, c) #4 5 54

# タプルの場合
data = (4,5,54)
a, b, c = data
print(a, b, c) #4 5 54

上記より、右辺の各要素が分解(アンパック)されて、左辺の各要素に代入されたことがわかります。

左辺の変数と右辺の要素数は必ず一致する必要があります。

変数と要素数が一致しない場合、ValueErrorが発生します。

data = [4,5,45,54]
a, b, c = data
# ValueError: too many values to unpack (expected 3)

data = [4,5,45,54]
a, b, c, d, e = data
# ValueError: not enough values to unpack (expected 5, got 4)

これより、必要のない要素があった場合でもその要素用に変数を用意しなければならないということです。

こういった場合にPythonではアンダーバー(アンダースコア)を利用します。
アンダーバーは値を保存せず無駄なメモリを使わないため積極的に利用しましょう。

data = (4,5,54)
a, b, _ = data

Pythonにおけるアンダーバーについては以下記事をご参照ください。

辞書のアンパック

辞書のアンパックはリストやタプルとは少し異なります。

リストやタプルのようにアンパックを行うと辞書のキーのみが変数に代入されます。

dictionary = {'English': 'normal', 'Japanese': 'dificult', 'Spanish': 'easy'}
a, b, c = dictionary
print(a, b, c)
# English Japanese Spanish

辞書のバリューを変数に代入したい場合はvalues()を利用します。

dictionary = {'English': 'normal', 'Japanese': 'dificult', 'Spanish': 'easy'}
a, b, c = dictionary.values()
print(a, b, c)
# normal dificult easy

辞書のキーとバリューの両方を変数に代入したい場合はitems()を利用します。

dictionary = {'English': 'normal', 'Japanese': 'dificult', 'Spanish': 'easy'}
a, b, c = dictionary.items()
print(a, b, c)
# ('English', 'normal') ('Japanese', 'dificult') ('Spanish', 'easy')

アスタリスク*の利用

アスタリスク*を利用すると、複数の変数に要素を代入する際に、分解されなかった残りの要素をまとめてリストとして代入できます。

data = (4,5,45,54)
a, b, *c = data
print(a) #4
print(b) #5
print(c) # [45, 54]

a, *b, c = data
print(a) #4
print(b) #[5, 45]
print(c) #54

*a, b, c = data
print(a) #[4, 5]
print(b) #45
print(c) #54

この機能はPython3から実装されました。

スワッピング

変数の値を入れ替えることスワッピングと呼びます。

このスワッピングはアンパック代入を利用すると簡単に実現できます。

a = 45
b = 54
a, b = b, a
print(a, b) #54 45

このスワッピングを利用した昇順のバブルソートの方法は後述いたします。

アンパックの活用

インデックスではなくアンパックを利用しよう

タプルの各要素を利用する際に、インデックスで各要素にアクセスができます。

data = (4,54)
a = data[0]
b = data[1]
print(a, b) #4 54

このようにインデックスを利用しても問題はありませんが、アンパック代入を利用することでより読みやすい、すっきりしたコードになります。

data = (4,54)
a, b = data
print(a, b) #4 54

アンパックでzip関数の利用

Pythonのzip関数は、複数のリストやタプルの要素をまとめる関数です。

アンパックはforループと組み合わせて利用する際に、zip関数を使用することが多いです。
forループ内で複数のリストやタプルの要素を同時に取得して利用したいときに使います。

language = ['English', 'Japanese', 'Spanish']
level = ['normal', 'difficult', 'easy']
for x, y in zip(language, level):
    print(x, y)
# English normal
# Japanese difficult
# Spanish easy

2つだけでなく、3つ4つと多くのリスト・タプルから同時取得ができます。

上記のようにして、複数のリストやタプルから要素をそれぞれ同時に取得できます。

昇順のバブルソート:アンパックとスワッピング

複数の数値を格納したリストを作成し、その数値を昇順にする関数bubbleを作ってみたいと思います。

リスト内の値を昇順にするバブルソートをインデックスを利用して実現すると次のようになります。

def bubble(x):
    for _ in range(len(x)):
        for i in range(1, len(x)):
            if x[i] < x[i-1]:
                temp = x[i]
                x[i] = x[i-1]
                x[i-1] = temp
values = [45, 54, 4, 5]
bubble(values)
print(values)
# [4, 5, 45, 54]

これをアンパックのスワッピングを利用して書くと次のようになります。

def bubble(x):
    for _ in range(len(x)):
        for i in range(1, len(x)):
            if x[i] < x[i-1]:
                x[i-1], x[i] = x[i], x[i-1]
values = [45, 54, 4, 5]
bubble(values)
print(values)

このようにアンパックを利用することでコードがとても短くなります。

まとめ

本記事「【Python】リスト・タプル・辞書:一度に要素を複数の変数に代入(アンパック)」はいかがでしたか。

アンパックを利用することで、コードが短くなり、見た目がとてもすっきりします。

ぜひアンパックを使って、読みやすいコードを書くようにしてください。