nikkie-ftnextの日記

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

Pythonの関数で可変長引数(*args、**kwargs)の型ヒントはどう書く?

関数本体では可変長位置引数(args)タプル、可変長キーワード引数(kwargs)辞書として扱われます。
これらの型ヒントには

  • タプルの要素
  • 辞書の値

の型を書けばよいです


はじめに

三重さん(のメガネ)はおうちに飾れる!1 nikkieです

タイトルの件が気になったので調べました。
結論は上述のとおりで、結論に至るまでの過程を綴っていきます。

目次

可変長引数を持った関数

PyCon JP 2022のトークの可変長引数のパートを出発点にします。

Pythonの関数は何個でも引数渡しをサポートするように定義できます2

  • 可変長個の位置引数
  • 可変長個のキーワード引数
f(1, 2, 3, a="hoge", b="piyo")

関数fは次のように定義されます

def f(*args, **kwargs):
    ...

  • 関数定義で*を付けた変数は、可変長個の位置引数を受け取れます
    • この変数はタプルを指します
  • 関数定義で**を付けた変数は、可変長個のキーワード引数を受け取れます
    • この変数は辞書を指します

可変長引数の型ヒント

ばばーん!

def f(*args: int, **kwargs: str) -> None:
    print(f"{args=}")
    print(f"{kwargs=}")


f(1, 2, 3, a="hoge", b="piyo")
  • *argsは、タプルの要素の型を型ヒントに書きます
    • 関数を定義した人が込めた気持ちとしては、位置引数としてintを渡してほしいということです
  • **kwargsは、辞書の値の型を型ヒントに書きます
    • 関数を定義した人が込めた気持ちとしては、キーワード引数としてstrを渡してほしいということです

動作確認環境は以下です:

根拠はPEP 484

型ヒントの始まりのPEP 484。
「Arbitrary argument lists and default argument values」に可変長引数の型ヒントについての記載があります。
https://peps.python.org/pep-0484/#arbitrary-argument-lists-and-default-argument-values

例として挙がっている関数定義

def foo(*args: str, **kwds: int): ...

In the body of function foo, the type of variable args is deduced as Tuple[str, ...] and the type of variable kwds is Dict[str, int].

意訳)関数fooの本体では、変数argsの型はTuple[str, ...](文字列を要素とするタプル)と推論され、変数kwdsの型はDict[str, int](キーが文字列、値が整数の辞書)と推論される3

可変長引数はタプルや辞書になると決まっている(型チェッカも承知している)ので、これらのコレクションの要素の型を型ヒントとして明示する必要があるのですね!

知ったきっかけ

一番最初に見つけたのが以下です。

この記事は短くまとまっていて分かりやすかったです(執筆に感謝)。
ここからPEP 484を知りました

終わりに

Pythonの関数で可変長引数の型ヒントは、コレクション(タプルや辞書)の要素の型を書く、という学びのアウトプットでした〜


  1. 教えていただきました(感謝)
  2. 位置引数キーワード引数実引数の種類です。こちらにまとめています
  3. PEP 484からPythonのバージョンアップが進み、Python 3.9以降はtyping.Tupleに代えて組み込みのtuple、typing.Dictに代えて組み込みのdictでの型ヒントができるようになっています(typing.Tupleとtyping.Dictは非推奨)