pexels-photo-5138888.jpeg

TypedDictでpythonのtype hintでdictのkeyとvalueに厳格に型をつける

 
0
このエントリーをはてなブックマークに追加
Kazuki Moriyama
Kazuki Moriyama (森山 和樹)

はじめに

この記事では、Pythonの型ヒントを使用してdict型のkeyとvalueの対応に厳格に型をつける方法を紹介します。

動作環境

  • Pythonの型チェックにはpyrightのstrict modeを使用します。
  • Python 3.8

組み込みDictの問題点

Pythonの組み込みのDict型は、厳格にkeyとvalueの対応付けを考慮した型付けができません。例えば以下のような関数があったとします。

def show_animal(a):
    print(a["name"])
    print(a["age"])

この関数は、nameageのkeyを持ち、かつnameとしてintを、ageとしてintを持つdictのみを受け取りたいとします。ただし、keyだけの制限ならLiteral型を使用すれば制約をかけられます。

from typing import Dict, Literal, Union

Animal = Dict[Literal["name", "age"], Union[str, int]]

def show_animal(a: Animal):
    print(a["name"])
    print(a["age"])

show_animal({"name": "taro", "age": 5}) # OK
show_animal({"name": "taro", "color": "black"}) # NG

しかし、Literal型だけではkeyとvalueの対応付けまでは制限をかけることができません。具体的には以下のような例が通ってしまいます。

show_animal({"name": 5, "age": "taro"}) # OK

このようなケースを許容したくない場合があります。

クラスを用いた解決

クラスを使用し、特に直積型のコンテナとして優れたdataclassを使用すれば、keyとvalueの型の対応付けが保証できます。

from dataclasses import dataclass

@dataclass
class Animal:
    name: str
    age: int

def show_animal(a: Animal):
    print(a.name)
    print(a.age)

show_animal(Animal("taro", 5)) # OK
show_animal(Animal(5, "taro")) # NG

しかし、クラスの定義はいいとして関数に渡すときには該当のインスタンスを生成する必要があります。dictのまま扱いたいときにはこの方法はそぐわないかもしれません。

TypedDictを用いた解決

TypedDictはdictのまま厳格に型を付けることができる便利なクラスです。

from typing import TypedDict

class Animal(TypedDict):
    name: str
    age: int

def show_animal(a: Animal):
    print(a["name"])
    print(a["age"])

show_animal({"name": "taro", "age": 5}) # OK
show_animal({"name": "taro", "color": "black"}) # NG
show_animal({"name": 5, "age": "taro"}) # NG

これで望み通りにkeyとvalueの対応に対して型が付けられます。TypedDictを用いた定義は継承以外にもいくつか方法が用意されているため、好みの方法で利用できます。

# 他の方法
Animal = TypedDict("Animal", name=str, age=int)
Animal = TypedDict("Animal", {"name": str, "age": int})

おわりに

Pythonの型ヒントと型チェックツールを用いた静的型検査は、しっかりと使うことで効果的にコードの品質を向上させることができます。型ヒントの恩恵を受けることで、より堅牢なプログラムを構築してください。

info-outline

お知らせ

K.DEVは株式会社KDOTにより運営されています。記事の内容や会社でのITに関わる一般的なご相談に専門の社員がお答えしております。ぜひお気軽にご連絡ください。