🐥

自作でintでenumを継承しなくても、IntEnumが標準化されてた

2024/08/26に公開

始めに

過去にPythonのenumはint等のプリミティブ型を継承すると便利という記事を投稿していました。

その後、Python3.11にてIntEnumStrEnumが標準化されていることを知ったので共有します。

環境

  • Python
    • 3.12.4

実装

intEnumの使用方法は次のとおりです。

from enum import IntEnum

class IntInheritEnum(IntEnum):
    ID = 1


# 列挙型ではなく、intとして振舞うため1にアクセスできる
IntInheritEnum.ID

# 本来のアクセス方法
IntInheritEnum.ID.value

ちなみに、intを継承したEnumとの相違点としてはIntEnumReprEnumを継承していることで、str()で期待する値を出力してくれる点がいいですね。実運用ではあまり大きな違いはないですが。

class IntInheritEnum(IntEnum):
    ID = 1

class IntInheritEnum2(int, Enum):
    ID = 1

# ログで動作確認するときにちょっとうれしい
print(IntInheritEnum.ID)
# 1
print(IntInheritEnum2.ID)
# IntInheritEnum2.ID

from pydantic import BaseModel
class Tmp(BaseModel):
    aaa: IntInheritEnum
    bbb: IntInheritEnum2

# pydanticでインスタンスをログ出力するときには効かないので微妙
# どこかのアップデートでReprEnumが使用されるようになる…?
print(Tmp(aaa=IntInheritEnum.ID, bbb=IntInheritEnum2.ID))
#  {'aaa': <IntInheritEnum.ID: 1>, 'bbb': <IntInheritEnum2.ID: 1>}

注意点

前回の記事でも記載した注意点ですが、Enumの型のままintとしても振舞えるので型ヒントをつけたりすると混乱します。

# intとして振舞うのでエラーならない
result: int = IntInheritEnum.ID + 10

# 型が違うのに計算できてしまうのは確かに違和感がある
def add(num1: int, num2: IntInheritEnum):
    return num1 + num2

ソースコード

終わりに

前の継承も難しい構文ではなかったのですが、ちょっと混乱させてしまう点があったのでPythonの標準としてIntEnumStrEnumを定義していただいて助かります。堂々と使える点が良いです。

参考記事

Discussion