🔠
Enumはいいな(Pydanticを添えて)【Python】
はじめに
Python の Enum
は、列挙型を定義するためのクラスです。列挙型は、定数の集合を名前付きで定義し、それらを明示的に扱えるようにすることで、コードの可読性と保守性を高めます。
Enumの基本
Enumの定義
enum
モジュールをインポートし、Enum
クラスを継承することで列挙型を定義できます。各メンバーは「名前と値」のペアです。
from enum import Enum
class Color(Enum):
RED = 'red'
GREEN = 'green'
BLUE = 'blue'
Enumの使用
Enum メンバーの名前と値には、それぞれ name
と value
でアクセスできます。
print(Color.RED.name) # 'RED'
print(Color.RED.value) # 'red'
Enumのメンバー取得
名前や値を指定してメンバーを取得できます。
print(Color['RED']) # Color.RED
print(Color('red')) # Color.RED
Enumの比較
同じクラス内であれば Enum メンバー同士を比較できます。
print(Color.RED == Color.RED) # True
print(Color.RED == Color.GREEN) # False
Enumのイテレーション
Enum は for ループでイテレートできます。
for color in Color:
print(color)
# Color.RED
# Color.GREEN
# Color.BLUE
Enumのメンバー一覧
list()
を使ってメンバーのリストを取得できます。
print(list(Color))
# [<Color.RED: 'red'>, <Color.GREEN: 'green'>, <Color.BLUE: 'blue'>]
また、__members__
属性を使うと、名前とメンバーの対応を辞書として取得できます。
print(Color.__members__)
# {'RED': <Color.RED: 'red'>, 'GREEN': <Color.GREEN: 'green'>, 'BLUE': <Color.BLUE: 'blue'>}
Enumのメソッド追加
Enum にメソッドを追加することも可能です。以下は「次の色」を取得する例です。
class Color(Enum):
RED = "red"
GREEN = "green"
BLUE = "blue"
UNKNOWN = "unknown"
+ def get_next_color(self):
+ colors = list(Color)
+ current_index = colors.index(self)
+ next_index = (current_index + 1) % len(colors)
+ return colors[next_index]
print(Color.RED.get_next_color()) # Color.GREEN
Pydanticを使ったEnumのバリデーション
Enumフィールドの使用
実際の開発では、Enum は Pydantic のようなデータバリデーションライブラリと併用することが多いです。たとえば、BaseModel
のフィールドに Enum を使うことができます。
from pydantic import BaseModel
class Item(BaseModel):
name: str
color: Color
Enumフィールドのデシリアライズ(JSON → モデル)
JSON からモデルを生成する際、Enum は値の文字列で指定できます。
json_data = '{"name": "Sample Item", "color": "red"}'
item_from_json = Item.model_validate_json(json_data)
print(item_from_json) # name='Sample Item' color=<Color.RED: 'red'>
不正な値を指定すると、バリデーションエラーが発生します。
invalid_json_data = '{"name": "Sample Item", "color": "black"}'
item_from_invalid_json = Item.model_validate_json(invalid_json_data)
print(item_from_invalid_json)
# pydantic_core._pydantic_core.ValidationError: 1 validation error for Item
# color
# Input should be 'red', 'green' or 'blue' [type=enum, input_value='black', input_type=str]
# For further information visit https://errors.pydantic.dev/2.11/v/enum
Enumフィールドのシリアライズ(モデル → JSON)
モデルから JSON を出力する場合、Enum は値の文字列になります。
item = Item(name="Sample Item", color=Color.RED)
json_data_from_item = item.model_dump_json()
print(json_data_from_item) # {"name": "Sample Item", "color": "red"}
Enumにデフォルト値を設定する(バリデーションカスタマイズ)
存在しない値が渡された場合に UNKNOWN
をデフォルトとするように、field_validator
を使用してカスタムバリデーションを追加することができます。
class Color(Enum):
RED = 'red'
GREEN = 'green'
BLUE = 'blue'
+ UNKNOWN = 'unknown'
class Item(BaseModel):
name: str
color: Color
+ @field_validator("color", mode='before')
+ def validate_color(cls, value: str):
+ try:
+ return Color(value)
+ except ValueError:
+ return Color.UNKNOWN
valid_json_data = '{"name": "Sample Item", "color": "black"}'
item_from_valid_json = Item.model_validate_json(valid_json_data)
print(item_from_valid_json) # name='Sample Item' color=<Color.UNKNOWN: 'unknown'>
参考資料
Discussion