Pyrhon♪関数の引数の「=」「:」「*」「**」を整理して覚えるためのポイント

ディフォルト値、キーワード引数、アンパック、「=」「:」「*」「**」などなど、覚えてしまえば簡単なのだと思いますが、「関数の引数に関する用語や記号はごちゃごちゃしてとっつきにくい。」というあなたに、整理して覚えるためのポイントを説明します。

1.「実引数」「仮引数」という言葉を覚えよう。

「実引数」は、関数を呼び出す側の引数。「仮引数」は、関数側の引数です。基本的なことかもしれませんが、まず、これをしっかり覚えましょう。そして、コード01がすぐに分かれば、簡単なプログラムを組む分には問題ないと思います。

なお、実引数と仮引数は同じ変数名である必要はありません。どの変数に値を渡すかは、原則、変数名ではなく位置できまります。したがって、この様に位置で決まる引数を位置引数と言います。コード01では、1番目の実引数の値は、1番目の仮引数の変数へ受け渡され、2番目の実引数の値は、2番目の仮引数の変数へ受け渡されます。
一方、後述のキーワード引数はこの原則から外れます。キーワード引数は位置ではなく、引数の名前で決まります。

#コード01
def xxx(a, b): #a, bが仮引数
    print('a, b =', a, b)

aa = 1
xxx(aa, 2) #aa, 2が実引数
bb = 2
xxx(bb, [4,5]) #bb, [4, 5]が実引数
#出力01
a, b = 1 2
a, b = 2 [4, 5]

2.「=」「:」は、実引数か、仮引数かを意識しよう。

引数の「=」、「:」は、実引数で使われているのか、仮引数で使われているのかを意識して覚えましょう。

(1) 実引数の「=」「:」と仮引数の「=」「:」

(a) 仮引数の「=」は引数のディフォルト値です。引数の初期値を設定する場合に用います。
(b) 実引数の「=」はキーワード引数です。仮引数の変数名を指定し、指定した引数に直接値を渡したい時に用います。
(c) 実引数で「:」は使いません。
(d) 仮引数の「:」は「関数注釈(関数アノテーション)」です。引数や返り値の注釈を記入できます。ディクショナリと混同しないようにしましょう。関数の注釈を記述すると、「関数名.__annotations__」で、引数や返り値の注釈を出力することができます。

まずは、ここまでをしっかりと頭にたたきこみましょう。ここまでがあやふやだと、混乱します。

(2) 使用例:実引数の「=」と仮引数の「=」

コード02の2行目、仮引数側の(a = 1, b = 2, c = 3)は「引数のディフォルト値」。6行目、実引数側の(c = 4, a = 5)は、キーワード引数です。(あえて、b をaより先に記述してみました。)なお、「=」が実引数で使われているのか、仮引数で使われているのかを意識しないと混乱します。

#コード02
#仮引数の「=」は引数のディフォルト値。イコールの左辺は変数名
def xxx(a = 1, b = 2, c = 3):
    print(a, b, c)

xxx(4, 5, 6)
xxx(c = 4, a = 5) #実引数の「=」はキーワード引数。イコールの左辺は変数名。
xxx()
#出力02
4 5 6
5 2 4
1 2 3

(3) 使用例:実引数の「:」と仮引数の「:」

コード03の「:'ハロー'」「:int」「->str」の部分が関数注釈(関数アノテーション)です。以下の例では、関数注釈ではreturnで返す結果をstrとしていますが、実際にはintを返しています。関数注釈は、単なる説明ですので、エラーにはなりません。

#コード03
#単なる説明なので、その通りにいれなくてもエラーにはならない。
def xxx(a:'ハロー', b:int = 2)->str:
    print('a, b =', a, b)
    return a + b

print(xxx(3, 4))
print(xxx.__annotations__)
#出力03
a, b = 3 4
7
{'a': 'ハロー', 'b': <class 'int'>, 'return': <class 'str'>}

3.「*変数名」「**変数名」の使い方

以下、「*変数名」シングルアスタリスク付き変数と「**変数名」ダブルアスタリスク付き変数の説明をします。

(1) 「*」「**」が受け渡しできるもの

(a)「*変数」シングルアスタリスク付き変数はタプル、リストを出し入れできる。
(b)「**変数名」ダブルアスタリスク付き変数はディクショナリを出し入れできる。なお、ディクショナリの要素の左側の「キー」は文字列にする必要がある。

(2) 実引数で用いる「*」「**」と仮引数で用いる「*」「**」

(a) 実引数で「*」を用いる。
タプル、リストの要素を位置引数にして渡すことができます。(タプル、リストからアンパックした位置引数を渡すことができます。)
(b) 実引数で「**」を用いる。
ディクショナリの要素をキーワード引数にして渡すことができます。(ディクショナリからアンパックたキーワード引数を渡すことができます)
(c) 仮引数で「*」を用いる。
実引数の位置引数が仮引数の位置引数より多い場合、多い分をタプルとして受け取ることができます。
(d) 仮引数で「**」を用いる。
実引数のキーワード引数に、仮引数にない名前のキーワード引数がある場合、それをディクショナリとして受け取ることができます。

(3) その他の注意点

(a) 「*」「**」を用いる時には実引数と仮引数の数をそろえることに注意。仮引数側に「*」「**」がある場合は引数の数を調整する機能がありますが、実引数側のみに「*」「**」を用いる時には数の調整ができないので注意が必要。
(b) ディクショナリの「:」と「関数注釈(関数アノテーション)」の「:」を混同しない。
(c) キーワード引数の「=」、引数のディフォルト値の「=」を混同しない。
(d) 実引数側のキーワード引数は、必ず、位置引数の後にしなければなりません。

(4) 使用例:仮引数だけ「*」「**」

コード04で、仮引数側では、実引数の位置引数1, 2, 3のうち1をaが受け取り、残りの2, 3を仮引数側の*bが受け取っています。仮引数側の*bには、引数の個数を調整する機能があります。
引数を調整する機能がありますので、「*引数名」は、他の位置引数の後に配置する必要があります。また、「**引数名」も同様に、他のキーワード引数の後に配置する必要があります。

#コード04
def xxx(a, *b, aa, **c):
    print(a, b, aa, c)

xxx(1, 2, 3, aa = 1, bb = 2, cc = [3])
#出力04
1 (2, 3) 1 {'bb': 2, 'cc': [3]}

(5) 使用例:実引数だけ「*」「**」

実引数側でシングルアスタリスク(*変数名)やダブルアスタリスク(**変数名)を用いる場合は、実引数側で引数の数を調整できませんので、仮引数側の引数の数に注意し、数をそろえなければなりません。コード05では、仮引数側の引数はa, b, c, aa, bbの5個ですので、実引数側も5個の引数を用意しています。

#コード05
def xxx(a, b, c, aa, bb):
    print(a, b, c, aa, bb)

b = [1, 2, 3]
c = {'aa':4, 'bb':5}
xxx(*b, **c)
#出力05
1 2 3 1 2

(6) 使用例:実引数と仮引数の両方に「*」「**」

また、7行目のキーワード引数の左辺はaa, ddであり表記が文字列ではありませんが、6行目のディクショナリーでは'bb, 'cc'と文字列になっています。混同しないようにしましょう。
キーワード引数である「**引数名」は、位置引数の後であれば、どの位置でも配置できます。例えば、コード06では、「**c」が、「dd = 7」の前に配置されています。同様に、位置引数である「*引数名」も、キーワード引数の前であれば、どの位置でも配置できます。

#コード06
def xxx(a, *b, **c):
    print(a, b, c)

b = [1, 2, 3]
c = {'bb':5, 'cc':6}
xxx(*b, aa = 4, **c, dd = 7)
#出力06
1 (2, 3) {'aa': 4, 'bb': 5, 'cc': 6, 'dd': 7}

以上、関数の引数の「=」「:」「*」「**」を整理して覚えるためのポイントを整理してみました。いかがでしょうか。