Python で定数を扱う際、単なる変数で管理する方法は手軽ですが、複雑な状態管理や選択肢が増えるとコードが煩雑になり、バグの温床となることがあります。こうした問題を解決するのがenum
モジュールです。本記事では、enum
の基本から実践的なユースケースまでを解説します。
enum モジュールとは
enum
は Python 3.4 以降で標準ライブラリに追加されたモジュールで、列挙型(Enum) を定義するための機能を提供します。列挙型は、複数の関連する定数をひとまとめに管理する手法で、可読性や保守性の向上に役立ちます。
基本的な使い方
Enum の定義
import enum
class Status(enum.Enum):
PENDING = 1
APPROVED = 2
REJECTED = 3
Status
クラスはenum.Enum
を継承しており、PENDING
、APPROVED
、REJECTED
が列挙型のメンバーです。- メンバー名は大文字で記述するのが一般的です。
メンバーへのアクセス
print(Status.PENDING) # Status.PENDING
print(Status.PENDING.name) # 'PENDING'
print(Status.PENDING.value) # 1
.name
で名前、.value
で値を取得できます。
文字列や値からの参照
print(Status['APPROVED']) # Status.APPROVED
print(Status(2)) # Status.APPROVED
Status['APPROVED']
は名前で参照。Status(2)
は値で参照します。
enum.auto()による自動採番
値を自動で付与したい場合はenum.auto()
が便利です。
class Priority(enum.Enum):
LOW = enum.auto()
MEDIUM = enum.auto()
HIGH = enum.auto()
print(Priority.LOW.value) # 1
print(Priority.MEDIUM.value) # 2
auto()
は定義順に 1 から自動採番します。
ユニーク制約: @unique デコレーター
@enum.unique
デコレーターを使用すると、値の重複を禁止できます。
from enum import unique
@unique
class ErrorCode(enum.Enum):
NOT_FOUND = 404
UNAUTHORIZED = 401
# FORBIDDEN = 404 # これを追加するとValueErrorが発生
- 同じ値を複数のメンバーに割り当てると
ValueError
が発生します。
実践的なユースケース
1. 状態管理(State Management)
状態遷移が発生する場面での使用例です。
class OrderStatus(enum.Enum):
PENDING = enum.auto()
PROCESSING = enum.auto()
SHIPPED = enum.auto()
DELIVERED = enum.auto()
def update_status(order_id, status: OrderStatus):
print(f"Order {order_id} is now {status.name}")
update_status(101, OrderStatus.PROCESSING)
- 状態を定義することで、不正な状態遷移を防止できます。
2. フラグ管理(Flag Management)
複数のフラグを組み合わせる場合はenum.Flag
が適しています。
from enum import Flag, auto
class Permission(Flag):
READ = auto()
WRITE = auto()
EXECUTE = auto()
user_perm = Permission.READ | Permission.WRITE
print(Permission.WRITE in user_perm) # True
print(Permission.EXECUTE in user_perm) # False
- ビット演算で権限の付与・確認が簡単にできます。
3. API レスポンスのステータス管理
API のステータスコードを管理する例です。
class APIStatus(enum.Enum):
SUCCESS = 200
BAD_REQUEST = 400
UNAUTHORIZED = 401
SERVER_ERROR = 500
def handle_response(status: APIStatus):
if status == APIStatus.SUCCESS:
print("Request successful")
else:
print(f"Error: {status.name}")
handle_response(APIStatus.BAD_REQUEST)
- ハードコードの排除で、バグの発生を防ぎます。
Enum の利点とベストプラクティス
メリット
- 可読性の向上: 定数に意味のある名前を付けられる。
- バグ防止: 無効な値や状態遷移を防げる。
- メンテナンス性: 状態や定数の変更が一元管理できる。
ベストプラクティス
- 大文字の定数名を使用する。
@unique
を活用して重複を防ぐ。- 値の自動採番には
auto()
を活用する。
まとめ
Python のenum
モジュールは、単なる定数管理だけでなく、状態遷移、フラグ管理、API レスポンス管理など幅広い用途で活用できます。複雑な条件分岐やマジックナンバーの排除に役立ち、コードの可読性と保守性を大幅に向上させます。定数が 3 つ以上になる場合や、状態の一意性が重要な場合は積極的に活用することをおすすめします。