Python3.12では、Python 3.12の新機能(その2) PEP 695: 型パラメータ文法 の他に、以下の型ヒント関連PEPが採択されています。
- PEP 692: Using TypedDict for more precise **kwargs typing
- PEP 698: Override Decorator for Static Typing
それぞれ簡単に紹介します。
PEP 692: TypedDictで**kwargs の型定義¶
Pythonの関数には、関数呼び出し時に任意の数の引数を渡せるように指定できます。これを可変長引数といいます。
次の例で、*args
は位置引数の可変長引数、**kwargs
はキーワード引数の可変長引数です。
def foo(*args, **kwargs):
pass
この関数は、好きな数の位置引数と、キーワード引数を指定して呼び出せます。
foo(1,2,3,a=4,b=5,c=6)
これまでのPythonでは、可変長引数に型ヒントを指定する特別な記法は用意されていなかったため、指定できる型は普通の引数と同じく、一つだけでした。次の例は、すべての位置引数は整数、すべてのキーワード引数は文字列と指定しています。
def foo(*args: int, **kwargs: str)->None:
pass
foo(1, 2, 3, a="abc", b="def") # OK: 位置引数が整数でキーワード引数が文字列
foo(1, "2", 3, a="abc", b="def") # NG: 位置引数として文字列を指定している
foo(1, 2, 3, a=100, b="def") # NG: キーワード引数として整数を指定している
Python3.12では、PEP 692: TypedDictで**kwargs の型定義 が採用され、可変長キーワード引数に型ヒントを指定できるようになりました。 可変長キーワード引数の型は、TypedDict と Unpack を使用します。
次の例では、キーワード引数として foo
、bar
、baz
を指定できます。
from typing import TypedDict, Unpack, NotRequired
class KwdArgsDict(TypedDict):
foo: str
bar: int
baz: NotRequired[float]
def func(**kwargs: Unpack[KwdArgsDict]):
pass
func(foo="foo", bar=100, baz=1.0) # OK
func(foo="foo", bar="100", baz=1.0) # エラー: barが文字列
func(foo="foo", bar=100) # OK: bazは省略可
func(foo="foo", baz=1.0) # エラー: barは省略不可
ここで Unpack
を書き忘れると、「すべてのキーワード引数は KwdArgsDict
型である」という宣言になってしまいます。
from typing import TypedDict, NotRequired
class KwdArgsDict(TypedDict):
foo: str
bar: int
baz: NotRequired[float]
def func(**kwargs: KwdArgsDict): # Unpackを使っていない
pass
func(foo={"foo":"a", "bar": 1, "baz": 1.0}) # OK: 引数がKwdArgsDict
func(foo="foo", bar=100, baz=1.0) # エラー: 引数がKwdArgsDictではない
@overrideデコレータ¶
PEP 698: Override Decorator for Static Typing は、基底クラスのメソッドをオーバーライドする派生クラスのメソッドを明示的に示す @override
デコレータを追加しました。
from typing import override
class Base:
def foo(self):
print("Base.foo()")
class Derive(Base):
@override
def foo(self):
print("Derive.foo()")
@override
デコレータを使用してメソッドのオーバーライドを明示すると、メソッドの用途が明確になります。また、基底クラスでオーバライド元のメソッドが削除されたり名前が変わったりした場合、型チェッカが変更を検出してエラーを出してくれます。