Pythonでは関数のパラメーターには幾つかの種類があり、引数の渡し方にも位置引数やキーワード引数といった種類があります。どのパラメーターにどの引数が渡されるのか、ちゃんと理解しているかをクイズで確認してみましょう。
以下は幾つかの引数を受け取る関数funcの定義と、それを呼び出すコードである。以下のように関数funcを呼び出したとき、パラメーターcの値は何になるか、選択肢の中から適切なものを選択せよ。
def func(a, /, b, *args, c):
print(f'{a=}, {b=}, {args=}, {c=}')
func(1, 2, 3, 4, 5, 6)
【選択肢】
というわけで、大好評(?)のPythonクイズ、第2回のお時間がやってまいりました。どうも、「へなちょこPythonistaかわさき」略して「HPかわさき」です。
週刊少年マンガ雑誌の新連載の第2回って、ホントに読者からの評判がよくってキャッチコピーに「大好評!」「人気沸騰!」とか付けてんの? と昔から謎に思っていました。もっとも、今では紙媒体でもSNSやインターネット上の掲示板で読者の反応を調べられるので、以前よりはこうしたキャッチコピーに対する疑問は薄らいできました(とはいえ、印刷に入るタイミングもあるしなぁ。ホントなのかなぁ)。
本フォーラム「Deep Insider」はWebメディアなので、記事のページビュー(PV)をリアルタイムにチェックできます。なので、第1回を多くの方に読んでいただけたかどうかくらいは分かるんです。その結果、「大好評(?)」くらいは書いていいんじゃないかなと今のところは考えています(笑)。
と、ヨタ話をここに書いているのは、問題文と答えが近過ぎるのはよくないんじゃないかと考えているからです。次回以降もここに毎回埋め草が入りますので、クイズと同じくらい、埋め草にどんなネタをひねり出してくるのかを楽しみにしてください(埋め草のためだけにHPかわさきというキャラが作られたといっても過言ではないのです)。
では、正解発表のお時間です。
正解は「4. 例外が発生する」でした。
その理由を簡単にまとめると、cはキーワード専用パラメーターですが、関数funcの呼び出し時に「c=……」のようにしてキーワード引数を関数に与えていないからです。
Windowsの対話環境で試したところを以下に示します。
エラーメッセージを読むと確かに「関数funcには1つのキーワード専用引数が必要だけど、それがありません」といった内容のテキストが書かれていますね。詳しい説明はこの後で。
Pythonの関数(メソッド)を呼び出すときには、次の2つの方法で引数を渡せます。
これらを混在させることも可能ですが、その場合には位置引数を先に書く必要があります。例えば、以下のようなint関数の呼び出しはOKです。
n = int('11', base=16)
しかし、以下の書き方はできません。
n = int(base=16, '11')
一方、関数を定義する際にパラメーターリストには、次のような種類のパラメーターを記述できます。
上の説明ではキーワード専用パラメーターの位置について「パラメーターリスト中の'*'よりも後」と書きましたが、これは単独の'*'だけではありません。可変長位置パラメーターは「*args」のように書きますが、この「*」も対象となることに注意してください。
図にすると、こんな感じです。
また、'/'よりも後、'*'よりも前にあるパラメーターは「位置またはキーワード」パラメーターとなります。パラメーターリストに'/'も'*'もなければ、全てのパラメーターが「位置またはキーワード」パラメーターです。
では、以上を踏まえて、問題文の関数定義を見てみましょう。
def func(a, /, b, *args, c):
print(f'{a=}, {b=}, {args=}, {c=}')
それぞれのパラメーターが何であるかを考えると次のようになります。
そして、関数呼び出しは次のようになっていました。
func(1, 2, 3, 4, 5, 6)
引数がどのパラメーターに渡されるかは次の通りです。
このように、パラメーターcに渡される値がありません。選択肢1の「6」のように、可変長位置パラメーターのargsに「(3, 4, 5)」が渡され、cに残りの「6」が渡されるような都合が良いことは起きません。選択肢の2と3についても同様です。Pythonは単純にパラメーターの種類に応じて、どの引数をどのパラメーターに渡すかを判断し、整合性が取れなければ例外を発生します。そして、ここではつじつまが合っていないのでTypeError例外が発生したというわけです。
ではパラメーターcに値をちゃんと渡すにはどうしたらよいでしょう。これにはキーワード引数を使って、例えば、次のように関数funcを呼び出します。
def func(a, /, b, *args, c):
print(f'{a=}, {b=}, {args=}, {c=}')
func(1, 2, 3, 4, 5, c=6) # a=1, b=2, args=(3, 4, 5), c=6
Pythonの関数や引数などについては「Python入門」の以下の記事が参考になります。
興味のある方は、ぜひ読んでくださいね。
Copyright© Digital Advantage Corp. All Rights Reserved.