Python

【Python】配列の要素を展開して変数に代入する方法を解説【アンパック】

この記事では、Python のアンパック(unpack)について解説します。

アンパックとは、配列の要素を展開して変数に代入することを言います。また、関数の引数としてリストや辞書を展開して渡すこともでき、とても便利です。

それでは、アンパックの使い方を見ていきましょう!

アンパックの基本

アンパックは、右辺にイテラブル、左辺にイテラブルの要素の数だけ変数を用意します。

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

変数1に要素1が、変数2に要素2が代入されます。

サンプル

以下のコードでは、要素が3つ格納されているタプルをアンパックしています。

person = (1, 'Mike', 21)

# 要素数が3なので変数を3つ用意
no, name, age = person

print(f'No. {no}, name: {name}, age: {age}')

実行結果

No. 1, name: Mike, age: 21

よく関数の戻り値をタプルでまとめた時なんかに使われます。

def func():
    return 1, 2, 3

one, two, three = func()
print(one, two, three)

実行結果

1, 2, 3

辞書のアンパック

辞書をアンパックする場合は少し特殊で先ほどと同じ要領でアンパックすると変数に key のみが渡されます。

d = {'one': 1, 'two': 2, 'three': 3}

v1, v2, v3 = d

print(v1)  # one
print(v2)  # two
print(v3)  # three

value をアンパックしたい場合は dict.values() を使います。

d = {'one': 1, 'two': 2, 'three': 3}

v1, v2, v3 = d.values()

print(v1)  # 1
print(v2)  # 2
print(v3)  # 3

key と value をまとめて受け取りたい場合は dict.items() を使います。

d = {'one': 1, 'two': 2, 'three': 3}

v1, v2, v3 = d.items()

print(v1)  # ('one', 1)
print(v2)  # ('two', 2)
print(v3)  # ('three', 3)

ネストされている配列のアンパック

ネストされている配列もアンパックすることができます。

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

print(a)  # 1
print(b)  # (2, 3)

ネストされた部分も展開したい場合は ()[] で囲うことで実現できます。

t = (1, (2, 3))
a, (b, c) = t

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

辞書の key と value もバラバラに受け取ることができる。

d = {'one': 1, 'two': 2, 'three': 3}

(k1, v1), (k2, v2), (k3, v3) = d.items()

print(k1, v1)  # 'one', 1
print(k2, v2)  # 'two', 2
print(k3, v3)  # 'three', 3

実行結果

one 1
two 2
three 3

不必要な値の受け取り

特に必要ないの値がある場合は、その値を アンダースコア(_) で受けとることで間違って使用しないようにします。

point = (1, 2, 3)
x, y, _ = point

print(x)  # 1
print(y)  # 2
print(_)  # 3

アンダースコアは複数指定できます。

point = (1, 2, 3)
x, _, _ = point

print(x)  # 1
print(_)  # 3

複数の要素を受け取る

変数の前に アスタリスク(*) を付けることで、複数の要素を受け取ることができます。

以下コードでは、配列の要素数に対して変数の数が少ないですが、アスタリスクの付いた変数があるため要素を複数受け取ってくれる。

t = (1, 2, 3)

a, *b = t

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

前の変数にも付けることができる。この場合、後ろの変数の数に合わせて要素を受け取ります。

t = (1, 2, 3)

*a, b = t

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

ちなみに、ネストされている配列をアスタリスクの付いた変数で受け取ると、以下のようになります。

t = (1, (2, 3))

a, *b= t

print(a)  # 1
print(b)  # [(2, 3)]
アスタリスクを付けた変数で値を受け取ると必ずリストになる。

t = (1, 2, 3)

*a, b, c = t

print(a)
# [1]

また、複数付けることはできません。

# これはエラー
*a, *b = t

引数に配列の要素を展開して渡す

リストやタプル、辞書をアンパックして関数などの引数に渡すことができます。

リストやタプルの場合

リストやタプルを展開しながら引数に渡すには、名前の先頭に *(アスタリスク) を付けます。

def func(a, b):
    print(a, b)

vals = [1, 2]

# *配列名
func(*vals)  # 1, 2
引数の数と指定した配列の要素数が同じじゃないとTypeError

特に可変長引数の場合は、とても楽に値を引き渡せます。

def func(*args):
    for arg in args:
        print(arg)


vals = [1, 2, 3]

# 通常
func(vals[0], vals[1], vals[2])
# 1
# 2
# 3

# アンパック
func(*vals)
# 1
# 2
# 3

辞書の場合

辞書の場合は、*(アスタリスク) を 2つ付けます。すると、辞書の key と value を使ってキーワード呼び出しをします。

def func(a, b):
    print(a, b)

d = {'a': 1, 'b': 2}

# **辞書
func(**d)
# 1 2

# func(a=1, b=2)と同等

キーワード呼び出しなので要素の順番が異なっても問題ありません。

def func(a, b):
    print(a, b)

d = {'b': 2, 'a': 1}

# **辞書
func(**d)
# 1 2

# func(b=2, a=1)と同等

辞書の可変長引数に使うと便利です。

def func(**kwargs):
    print(kwargs)

d = {'one': 1, 'two': 2, 'three': 3}

func(**d)  # {'one': 1, 'two': 2, 'three': 3}

しかし、key と引数名が一致しない場合はエラーとなります。

def func(a, b):
    print(a, b)


d = {'a': 1, 'c': 2}
func(**d)  # TypeError: func() got an unexpected keyword argument 'c'
アスタリスクを1つに

実はアスタリスク1つでも辞書を展開し、引数に渡すことができます。その場合、key のみが渡されます。

def func(*args):
    for arg in args:
        print(arg)


d = {'one': 1, 'two': 2, 'three': 3}

func(*d)
# one
# two
# three

value のみを渡したい場合は、valuesメソッド を使います。

func(*d.values())
# 1
# 2
# 3

まとめ

この記事では、Python のアンパックの使い方について解説しました。

アンパックすることでめんどくさいコードを簡潔に記述することができます。何気にけっこう使うので覚えておくと便利です❗️

それでは今回の内容はここまでです!ではまたどこかで〜( ・∀・)ノ