[Pythonチートシート]関数定義編Pythonチートシート

Pythonの関数定義と、位置引数/キーワード引数/可変長法引数を受け取る方法。ラムダ式についてギュッとまとめた。

» 2020年01月14日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「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)

myfunc2関数の呼び出し例

 最初の呼び出し例では、引数「1」と「2」はパラメーターaとbに位置引数として渡される。引数「3」はパラメーターargs(タプル)の要素となる。引数「x=4」はパラメーターkwargs(辞書)の要素「{'x': 4}」となる。2つ目の例では、パラメーターaとbにキーワード引数として値「1」と「2」が渡され、他の2つのキーワード引数はいずれもパラメーターkwargsに渡される。

 実行結果を以下に示す。

実行結果 実行結果

 なお、これらはパラメーターリストの末尾に置く。ただし、可変長位置引数を受け取るパラメーターは、パラメーターリスト中で位置引数の最後に置くことができる。その場合、それ以降のパラメーターはキーワード専用引数として扱われる。

 以下に例を示す。

def myfunc3(a, b, *args, c, **kwargs):
    print(f'a: {a}, b: {b}, args: {args}, c: {c}, kwargs: {kwargs}')

可変長引数を受け取るパラメーターを関数定義の例(その2)

 ここでは位置引数を受け取るパラメーターの最後として可変長位置引数を受け取るパラメーターargsを置いている。そのため、パラメーターcにはキーワード引数形式でしか値を渡せないことに注意しよう。パラメーターkwargsはそれ以外のキーワード引数を受け取る。呼び出し例を以下に示す。

myfunc3(1, 2, 3, 4, c=5, d=6, e=7)
myfunc3(1, 2, 3, 4, d=5)

myfunc3関数の呼び出し例

 1つ目の呼び出し例では、最初の2つの引数がパラメーターaとbに渡され、残る2つの位置引数はパラメーターargsの要素となり、キーワード引数「c=5」はパラメーターcに、残る2つのキーワード引数はパラメーターkwargsに渡される。

 一方、2つ目の呼び出し例では、キーワード引数として値を渡すしかないパラメーターcに値が渡されないため、例外が発生する。

実行結果 実行結果

 可変長引数を受け取るパラメーターを持たせる際には、それをパラメーターリスト中のどこに置くかは注意しよう。

ラムダ式

 最後にラムダ式の定義についてもまとめておこう。ラムダ式は、1行で処理が終わる無名の関数を簡単に定義するのに使える。これは、関数の引数として関数を渡す場面などで便利に使える。つまり、関数本体が1行で済むような関数を事前に定義することなく、関数が必要な場所ですぐに関数を定義して利用できる。

 ラムダ式の構文を以下に示す。

lambda パラメーターリスト:

ラムダ式の構文

 「パラメーターリスト」にはそのラムダ式が必要とするパラメーターをカンマ区切りで並べる。「式」には、そのラムダ式で実行する処理を単一の式で記述する。書けるのは単一の式のみなので、おのずとラムダ式(が定義する関数)で行える処理は極めて小規模なものになる。

 以下に例を示す。

mylist = list(range(5))  # [0, 1, 2, 3, 4]
newlist = list(map(lambda x: x ** 2, mylist))

ラムダ式の利用例

 ここではmap関数の引数としてラムダ式を利用している。このラムダ式「lambda x: x ** 2」では先ほどの「パラメーターリスト」には「x」のみを指定し、「式」の部分には「x ** 2」とそれを2乗する式を書いている。この式の評価結果が、ラムダ式の戻り値となる。つまり、これは以下の関数を定義して、map関数に渡しているのと同じ意味になる。

def square(x):
    return x ** 2

mylist = list(range(5))
newlist = list(map(square, mylist))

上と同じ意味のコード

 ラムダ式を使った方が、コードが簡潔になることが分かる。なお、上記のmap関数呼び出しと、その結果(イテレータ)をlist関数に渡してリストを生成する処理自体はリスト内包表記を使うと次のように書ける。

mylist = list(range(5))
newlist = [x ** 2 for x in mylist]

リスト内包表記で同じことを行う

 ここではラムダ式の使用例として、map関数を用いたが、実際にはこちらの書き方がよいだろう。

 最後にラムダ式を返す関数を定義する例も示しておこう。関数を返す関数の例も並記するので見比べてほしい。

def get_incrementer(x):
    return lambda y: x + y

def get_incrementer2(x):
    def incrementer(y):
        return x + y
    return incrementer

one_incrementor = get_incrementer(1)
two_incrementor = get_incrementer2(2)

print(one_incrementor(1))
print(two_incrementor(1))

ラムダ式を返す関数と関数を返す関数


 今回は関数定義についてまとめた。次回は、文字列やリスト、タプルなど、反復可能オブジェクトの操作についてまとめる。

「Pythonチートシート」のインデックス

Pythonチートシート

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。