Python3.12の新機能 Python 3.12の新機能(その3) その他の型ヒント関連機能

PEP 701: f文字列の形式定義PEP 695: 型パラメータ文法その他の型ヒント関連機能PEP 688: バッファープロトコルをPythonで利用可能にPEP 684: インタープリター別GILPEP 683: 固定参照カウントによる永続オブジェクトPEP 709: 内包式のインライン化

Python3.12では、Python 3.12の新機能(その2) PEP 695: 型パラメータ文法 の他に、以下の型ヒント関連PEPが採択されています。

それぞれ簡単に紹介します。

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 の型定義 が採用され、可変長キーワード引数に型ヒントを指定できるようになりました。 可変長キーワード引数の型は、TypedDictUnpack を使用します。

次の例では、キーワード引数として foobarbaz を指定できます。

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 デコレータを使用してメソッドのオーバーライドを明示すると、メソッドの用途が明確になります。また、基底クラスでオーバライド元のメソッドが削除されたり名前が変わったりした場合、型チェッカが変更を検出してエラーを出してくれます。

Copyright © 2001-2023 python.jp Privacy Policy python_japan
Amazon.co.jpアソシエイト
Amazonで他のPython書籍を検索