🔠

Enumはいいな(Pydanticを添えて)【Python】

に公開

はじめに

Python の Enum は、列挙型を定義するためのクラスです。列挙型は、定数の集合を名前付きで定義し、それらを明示的に扱えるようにすることで、コードの可読性と保守性を高めます。

Enumの基本

Enumの定義

enum モジュールをインポートし、Enum クラスを継承することで列挙型を定義できます。各メンバーは「名前と値」のペアです。

from enum import Enum

class Color(Enum):
    RED = 'red'
    GREEN = 'green'
    BLUE = 'blue'

Enumの使用

Enum メンバーの名前と値には、それぞれ namevalue でアクセスできます。

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'>

参考資料

https://docs.python.org/ja/3.13/library/enum.html
https://docs.python.org/ja/3.13/howto/enum.html
https://docs.pydantic.dev/2.0/usage/types/enums/
https://docs.pydantic.dev/latest/concepts/validators/

Discussion