nikkie-ftnextの日記

イベントレポートや読書メモを発信

1月の #stapy で挙がった2つの質問に回答します:キーワード専用引数はいつから? 位置専用引数の使い所は?

はじめに

秘密はね、最後に明かされるんだよ。nikkieです。

まず1スタッフとしてお礼を。
1/27(木)開催のみんなのPython勉強会、ご参加ありがとうございました。

「いろんなPythonを探検しよう」というテーマで、

  • Pythonという言語のここ5バージョンの変遷
  • パッケージングの基礎
  • NVIDIAさんの研究開発動向

と知られて、とても楽しかったです。

この記事では、laugh_kさんの登壇中に出た2つの質問を深堀ります。

  • キーワード専用引数はどのPythonバージョンから?
  • 位置専用引数はどんなときに使う?

Pythonのドキュメントを探したところ、どちらも私はちょっと驚いた答え(秘密)がありました。

目次

laugh_kさんトーク「Python3.6から3.10までのおよそ5年間の間の進化を振り返る」

laugh_kさん視点で、主観を交えて、振り返ったトークです。
PEPやWhat's Newを引きながらの振り返りで、「そうそう!」と楽しく聞いていました。
スライドを見返すだけでも楽しいと思います!

Python 3.8の振り返りの1つがPEP 570の位置専用引数(Positional-Only Parameters)です。

こちらについて、上記の2つの質問がZoomチャットやSlidoで出ました。

位置専用引数・キーワード専用引数について手短に

Pythonチュートリアルの説明を引用します。
https://docs.python.org/ja/3/tutorial/controlflow.html#special-parameters

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
    ...
  • pos1, pos2位置専用引数
    • pos1="ham" のようにキーワード引数として指定できません
  • pos_or_kwd:位置またはキーワード引数
    • 位置引数としても、キーワード引数としても指定できます
  • kwd1, kwd2キーワード専用引数
    • 位置引数として指定できません

文法上の説明としては

  • / の前までが位置専用引数
  • / の後から * の前までが、位置またはキーワード引数
  • * の後がキーワード専用引数

となります。
なお、/* はオプションであり、指定しない場合はすべての引数が位置またはキーワード引数となります。

それでは、質問に順番に答えていきます。

質問1:キーワード専用引数はどのPythonバージョンから?

laugh_kさんの振り返りにあるように、位置専用引数はPython 3.8からです。
ではキーワード専用引数はどのバージョンからでしょうか?

答えが浮かんでから読み進めるのをオススメします。


すぐに答えが見えないように、オススメの映画を宣伝しておきます。面白いからみんな観て!


私の答えは「Python 3.8」でしたが、これはブッブーでした。
Python 3.8を機に /* の説明をPythonチュートリアルで見かけるようになったと思っていたのですが、実は * (キーワード専用引数)はもっと前からあったんです。

いつからだと思いますか?

実は、キーワード専用引数は PEP 3102 で提案されているんです!

質問1への回答は Python 3.0 です。

def compare(a, b, *, key=None):というコードに以下の説明がされています:

The second syntactical change is to allow the argument name to be omitted for a varargs argument.

*argsのような可変長位置引数の変数名を削って * としたようです。

私はPython 3.6から触り始めたのですが、「入門時にはキーワード専用引数はあったんだなー」と分かって、Python 3.8まで知らなかったことに驚きました。

質問2:位置専用引数はどんなときに使う?

振り返りで登場した「位置専用引数」の利用シーンの質問です。

Effective Python 第2版』で読んだ記憶があったので、勉強会中に以下を共有しました。

「Effective Pythonにしか書かれていないのかな」と気になり、Pythonのドキュメントの中を探したところ、質問への回答がありました。

Pythonチュートリアルにあった「要約」

https://docs.python.org/ja/3/tutorial/controlflow.html#recap

  • もし引数の名前をユーザーに知らせる必要がないなら、位置専用引数を使用しましょう。
  • APIの場合、将来引数の名前が変更された場合にAPIの変更ができなくなることを防ぐために、位置専用引数を使用しましょう。

利用シーンは、ユーザが引数の名前を知らなくてもいいときや引数の名前を変更する可能性があるときということですね。
この要約にはキーワード専用引数についても載っています。

What's New in Python 3.8

https://docs.python.org/ja/3.8/whatsnew/3.8.html#positional-only-parameters

One use case for this notation is that it allows pure Python functions to fully emulate behaviors of existing C coded functions.

(意訳気味:この記法の1つのユースケースは、純粋なPythonの関数が既存のCのコードの関数と完全に同じ振る舞いをするのを可能にすることです)

もう一つのユースケースは、引数名が有用ではない場合にキーワード引数としての利用を排除することです。(略)これにより、以下のようなぎこちない呼び出しが排除されます:

チュートリアル同様に、引数名変更のメリットも書かれています。

引数を位置専用とすることは、のちに引数名を変更する際に呼び出し側のコードを壊してしまう心配がないという利点があります。

まとめ

冒頭の質問への回答をまとめます。

  • キーワード専用引数はどのPythonバージョンから? 👉 Python 3.0
    • PEP 3102で導入された
  • 位置専用引数はどんなときに使う? 👉 以下に抜粋
    • ユーザが引数の名前を知らなくてもいいとき
    • 引数名が有用でない場合(キーワード引数として使えなくすることで、可読性を上げる)
    • APIの場合(将来引数名を変更できるようにする)

位置専用引数の利用シーンが分かったので、普段の開発で積極的に使っていけそうです。
私が書くコードには、使いどころが結構あるように感じています。