メモ帳

python, juliaで機械学習をやっていく

アンパック代入を使って代入を簡単にする

pythonでは、「*args」や、「**kwargs」を使ってcollections型の変数を一括代入or受取できます。これは、アンパック代入と言われています。これを使って代入or受取を簡単にできる例をあげていきます。

アンパック代入とは

まず、アンパック代入を使うと、以下のように配列形式のデータを要素単位に分解して代入してくれます。使えるのはリスト、タプル、ジェネレータ、辞書などです。

args = [1, 2, 3, 4, 5]
print(args)
# >>> [1, 2, 3, 4, 5]

print(*args)
# >>> 1 2 3 4 5

辞書型にたいしては、以下のように代入する値を換えられます。

args_dict = {'aaa': 1, 'bbb': 2, 'ccc': 3}

# keyをアンパック代入
print(*args_dict)
# >>> aaa bbb ccc

# valueをアンパック代入
print(*args_dict.values())
# >>> 1 2 3

関数に代入したさい、関数側ではどのように制御するのかもう少し詳しく見ていきます。 ここで、引数定義にアンパックを使った例を紹介します。ここでは、4つ目以降の引数がタプル型でargsに代入されます。引数が可変長の場合は必ず使う必要がでてくると思います。

def func(first, second, third, *args):
    print(f'first: {first}')
    print(f'second: {second}')
    print(f'third: {third}')
    print(f'args: {args}')

func(1, 2, 3, 4, 5)
# >>> first: 1
# >>> second: 2
# >>> third: 3
# >>> rest: (4, 5)

このようにして定義した関数にアンパック代入すると、関数はどのように値を受け取るのか確認してみましょう。

args = [1, 2, 3, 4, 5]

func(args)
# >>> first: 1
# >>> second: 2
# >>> third: 3
# >>> rest: (4, 5)
# func(1, 2, 3, 4, 5)と同じ出力

ここから分かるように、アンパック代入は文字通り配列形式の変数の要素を一つずつとりだして、順番に値を代入していきます。

まとめ

変数の頭に*をつけると以下の2つの役割を果たすことを説明しました。

  1. 配列形式のデータを展開して関数に代入できること
  2. 関数の引数定義に使うとタプル型で可変長の引数を受け取れること

**の場合

*を2つ使うと働きがかわります。辞書型に使えて、keyをキーワードとするキーワード引数に展開して代入してくれます。

def func(first='', second='', ):
    print(f'first: {first}')
    print(f'second: {second}')

kwargs = {'first': 'aaa', 'second': 'bbb'}
func(**kwargs)
# >>> first: aaa
# >>> second: bbb

引数定義に使うと、明示的に定義していないキーワード引数が宣言した変数に代入されます。

def func(first='', second='', **kwargs):
    print(f'first: {first}')
    print(f'second: {second}')
    print(f'kwargs: {kwargs}')

kwargs = {'first': 'aaa', 'second': 'bbb', 'third': 'ccc'}
func(**kwargs)
# >>> first: aaa
# >>> second: bbb
# >>> kwargs: {'third': 'ccc'}

まとめ

変数の頭に**をつけると以下の2つの役割を果たすことを説明しました。

  1. 辞書型のデータを展開して関数のキーワード引数に代入できること
  2. 関数の引数定義に使うと明示的に宣言していないキーワード引数を受け取れること