[Pythonチートシート]関数定義編:Pythonチートシート
Pythonの関数定義と、位置引数/キーワード引数/可変長法引数を受け取る方法。ラムダ式についてギュッとまとめた。
前回の最後には関数定義の基本を簡単にまとめた。今回は関数定義について少し詳しくまとめよう。関数についての詳細は「Python入門」の「Pythonの関数」など関数について触れている回を参照されたい。
関数定義の基本
前回述べたように、Pythonで関数を定義する際の基本構文は以下のようになる。
def 関数名(パラメーターリスト):
関数本体のコード
return 戻り値
呼び出し側から受け取る値を保存する変数をパラメーターリストに記述し、関数本体のコードではそれらを利用して、何らかの処理を行い、return文で呼び出し側に値を返すのが基本だ。ただし、Pythonでは関数に値(引数、実引数)を渡す際には幾つかのやり方がある。以下ではそれらについてまとめていこう。
位置引数とキーワード引数
関数を呼び出す際に、それに渡す値のことを引数(実引数)と呼ぶ。引数の渡し方にはおおまかに分けて次の2種類がある。
- 位置引数:関数呼び出し時にカンマ区切りで並べた引数がそのままの順序でパラメーターに渡される
- キーワード引数:関数定義時のパラメーターリストに示したパラメーター名を使い、「パラメーター名=値」とすることで、パラメーターとその値を明記する引数の渡し方
以下に例を示す。
from math import sqrt
def get_distance(x1, y1, x2, y2):
distance = sqrt((x1-x2) ** 2 + (y1-y2) ** 2)
return distance
distance = get_distance(1, 1, 0, 0) # 位置引数
print(distance)
distance = get_distance(x1=2, y1=2, x2=0, y2=0) # キーワード引数
print(distance)
distance = get_distance(3, 3, y2 = 0, x2 = 0) # 位置引数とキーワード引数の混在
print(distance)
この例では位置引数のみ、キーワード引数のみ、位置引数とキーワード引数の混在の3種類方法で関数に引数を渡している。これらは全て問題なく動作する。
ただし、位置引数とキーワード引数を混在させる際には、「キーワード引数を指定するのは位置引数よりも後」という制約があることには注意が必要だ。例えば、以下のコードは例外を発生する。
distance = get_distance(x1 = 1, 1, 2, 2) # 例外
なお、Python 3では以前よりパラメーターリストで「キーワード専用パラメーター」を指定可能だった(キーワード引数形式でしか値を渡せないパラメーター)。これに追加して、Python 3.8以降では「位置専用パラメーター」つまり「位置引数としてのみ値を渡せる」パラメーターを明記できるようになった。パラメーターリストの記述時に、スラッシュ「/」を置くと、それよりも前にあるパラメーターは「位置専用パラメーター」になり、アスタリスク「*」を置くと、それよりも後ろにあるパラメーターには「キーワード専用パラメーター」になる。
以下に例を示す。
def myfunc(a, b, /, c, *, d, e):
print(f'a: {a}, b: {b}, c: {c}, d: {d}, e: {e}')
この場合、スラッシュ「/」よりも前にある2つのパラメーターaとbは位置専用パラメーターだ。一方、アスタリスク「*」よりも後ろにある2つのパラメーターdとeにキーワード専用パラメーターだ。間にあるパラメーターcは位置引数としても、キーワード引数としても値を渡せる。以下に例を示す。
myfunc(0, 1, 2, d=3, e=4) # 問題なし
myfunc(0, 1, d=3, e=4, c=2) # 問題なし
myfunc(a=0, b=1, c=2, d=3, e=4) # 例外
myfunc(0, 1, 2, 3, 4) # 例外
上の例では、最初の2行は例外を発生させることなく呼び出せる。これは最初の2つの位置専用パラメーターは位置引数を使って値を渡し、他のパラメーターにはキーワード引数形式で値を渡しているからだ。その下の2行は位置専用パラメーターにキーワード引数を使って値を渡そうとしたり、キーワード専用パラメーターに位置引数形式で値を渡そうとしたりしているために例外が発生する。
以下はPython 3.8.1上にJupyter Notebook環境を構築して、その上で上記コードを実行した結果だ(3行目と4行目では例外の種類が違うので、環境がある方は試してみよう)。
デフォルト引数値
関数のパラメーターには「デフォルト引数値」を持たせることができる。デフォルト引数値を持つパラメーターは関数呼び出し時に、その値の指定を省略でき、省略した場合にはデフォルト引数値が指定されたものとして扱われる。関数が多くのパラメーターを持ち、それらが一般には既定の値(デフォルト値)を指定すればよいという状況ではデフォルト引数値を持たせると関数を呼び出す側が毎回毎回同じ値を指定する必要がなくなり、便利に使えるようになる。
デフォルト引数値はパラメーターリストの中で「パラメーター名=デフォルト引数値」のようにして指定する。ただし、デフォルト引数値を持つパラメーターは、それを持たないパラメーターよりもリストの中で後ろに置く必要がある。以下に例を示す。
from math import sqrt
def get_distance(x1, y1, x2=0, y2=0):
distance = sqrt((x1-x2) ** 2 + (y1-y2) ** 2)
return distance
これは2点間の位置を計算する関数だが、ある1点と原点との距離を計算することはよくある。そのため、ここでは第3パラメーターと第4パラメーターでは原点を意味する整数値0をデフォルト引数値として指定している。
呼び出し例を以下に示す。最初の例では全ての引数を指定し、次の例ではデフォルト引数値を省略している(実行結果は省略)。
print(get_distance(2, 2, 1, 1)) # 全ての引数を指定
print(get_distance(2, 2)) # デフォルト引数値を持つものについては指定を省略
可変長引数
関数に任意の個数の引数を渡せるようにもできる。これには可変長引数リスト(任意引数リスト)を使用する。既に見た通り、Pythonでは引数渡しの方法に位置引数とキーワード引数の2つの方法があるため、可変長引数についてもこれらに対応したものがある。
- 可変長位置引数を受け取るパラメーター:パラメーターリスト内でアスタリスク「*」を前置してパラメーターを置く
- 可変長キーワード引数を受け取るパラメーター:パラメーターリスト内でアスタリスク2つ「**」を前置してパラメーターを置く
前者には、関数呼び出し時に関数に渡された位置引数のうち、パラメーターリストで対応するものを持たないものがタプルの要素として保管される。このパラメーターの名前としては「args」を使うのが一般的だ。同様に後者には、関数呼び出し時に関数に渡されたキーワード引数のうち、パラメーターリストで対応するものを持たないものが辞書の要素として保管される。このパラメーターの名前としては「kwargs」を使うのが一般的だ。
以下に例を示す。
def myfunc2(a, b, *args, **kwargs):
print(f'a: {a}, b: {b}, args: {args}, kwargs: {kwargs}')
この例では、パラメーターaとbは位置引数としてもキーワード引数としても値を渡せる。これら2つがmyfunc2関数を呼び出すのに必須のパラメーターとなる。そして、それ以上の引数が渡されたときには、位置引数はパラメーターargsに、キーワード引数はパラメーターkwargsに渡される。以下に例を示す。
myfunc2(1, 2, 3, x=4)
myfunc2(x=3, y=4, b=2, a=1)
最初の呼び出し例では、引数「1」と「2」はパラメーターaとbに位置引数として渡される。引数「3」はパラメーターargs(タプル)の要素となる。引数「x=4」はパラメーターkwargs(辞書)の要素「{'x': 4}」となる。2つ目の例では、パラメーターaとbにキーワード引数として値「1」と「2」が渡され、他の2つのキーワード引数はいずれもパラメーターkwargsに渡される。
Copyright© Digital Advantage Corp. All Rights Reserved.