mypyとTypedDictとtotalオプションについて

pythonでもdictに型を付けたいですね。一応TypedDictという型を定義したいという動きになっています。ちなみにまだこの機能はexperimentalになっているので。mypy_extensionsの方に入っています。

import mypy_extensions as mx


class Pair(mx.TypedDict):
    left: int
    right: int


d0: Pair = {"left": 0, "right": 0}
# もしくは
d1 = {"left": 0, "right": 0}  # type: Pai

mypy_extensions

ついでに寄り道、mypy_extensionsについて、基本的にpythonの型関連の機能は以下の順でnitghtlyからstableというような遷移をします。

  • mypy_extensions -- experimental
  • typing_extensions -- nightly
  • typing -- stable

(併記した修飾子は勝手に付けたものです)

例えば、Protocolなんかはtyping_extensionsですね。

ちなみにこのissueでtyping_extensionsにしようよ。という話が出ています。

TypedDictの定義

TypedDictの型の定義の仕方は、クラス定義likeにやる方法とcollectionsのクラスファクトリーlikeにやる方法の2種類があります。

# クラス定義likeにやる場合

class Pair(mx.TypedDict):
    left: int
    right: int

# collectionsのクラスファクトリーlikeにやる場合の2種類があります。
Pair = mx.TypedDict("Pair", {"left": int, "right": int})

TypedDictの型の扱われ方

例えば以下のような値がだめになります。

class Pair(mx.TypedDict, total=True):
    left: int
    right: int


# 未定義のkeyを保持
d0: Pair = {"left": 0, "right": 0, "middle": 0}

# 欠損している
d1: Pair = {"left": 0}

# 型が異なる
d2: Pair = {"left": "0", "right": "0"}

欠損値を含む値を許可する(total=False)

欠損値を含んだdictを取り扱いたいときもあると思います。totalというoptionがあります。defaultではTrueです。

このtotalをFalseにすると以下の欠損値を含むコードも全部OKになります。

class Pair(mx.TypedDict, total=Fase):
    left: int
    right: int


d0: Pair = {"left": 0, "right": 0}
d1: Pair = {"left": 0}
d2: Pair = {}

欠損値を含んだtypedDictとのintersection(多重継承)

これはいい感じにやってくれます。

import mypy_extensions as mx


class Person(mx.TypedDict, total=True):
    name: str
    age: int


class HasNickname(mx.TypedDict, total=False):
    nickname: str


class PersonHasNickname(Person, HasNickname):
    pass


# ok
d0: PersonHasNickname = {"name": "foo", "age": 20, "nickname": "F"}

# ok
d1: PersonHasNickname = {"name": "foo", "age": 20}

# error: Key 'age' missing for TypedDict "PersonHasNickname"
d2: PersonHasNickname = {"name": "foo", "nickname": "Fq"}

**kwargsみたいな他の値も取れるようなTypedDictは?

例えば、a:int,b:intという2つのkeyに対しては型が決まっているが、他はanyみたいなdictについての対応のことです。これはまだissueの段階。 (例えば、open api specのformatのサードパーティ用の属性のx-foo-barみたいな部分の対応とかで使いそうです)

generics的なものは?

まだ

参考

totalの話は実際の所しっかりドキュメントに書いてあるので。ちゃんと読めば大丈夫。