この記事では、Pythonで列挙型を使う方法を解説します。
列挙型(Enum)とは、抽象データを定義するための機能で、性別などのマジックナンバーを使ってしまいそうな値を型として定義することができます。
例えば、以下のようなコードを見たことありませんか?
# 性別を表す変数 gender = 0 if gender == 0: print('男性') else: print('女性')
このコードは、genderの値が「0ならば男性」「0以外ならば女性」と出力するコードですが、値自体にはなんの関連性もなく、人によっては「0 = 女性」「1 = 男性」と定義するかもしれません。
このようなコードは、直感的にわかりずらく思い込みや勘違いから無用な問題を引き起こす可能性があり、あまりいいコードとは言えません。
そこで 列挙型の出番です!
列挙型(Enum)を使う
列挙型は、enumモジュールのEnumクラスを継承させることで使用できます。
先ほどの性別を列挙型にすると、以下のようになります。
※ 今回は分かりやすいように日本語で定義しました。
from enum import Enum class Gender(Enum): 男性 = 0 女性 = 1
これでGenderという性別を表す列挙型が定義できました。
では、列挙型を用いて最初のコードを書き直してみましょう!
すると、以下のようになります。
gender = Gender.男性 if gender == Gender.男性: print('男性') else: print('女性')
上記コードでは、マジックナンバーを使わずに定義でき、見ただけで男性を指定していることがわかります。このように、列挙型を使うことで抽象的な概念を型として定義することができます。
それでは、列挙型の定義方法や使い方をもう少し詳しく見ていきましょう!
列挙型の定義
列挙型は、enumモジュールのEnumクラスを使って定義します。enumモジュールは、標準ライブラリなのでインポートするだけで使えます。
from enum import Enum
インポートしたEnumクラスから派生クラスを定義します。
from enum import Enum class クラス名(Enum): ...
クラス内には、列挙型の値としてnameとvalueを定義します。
from enum import Enum class クラス名(Enum): name1 = value1 name2 = value2 ・ ・ ・ nameN = valueN
変数名がname、値がvalueとして扱われます。
列挙型の呼び出し
次に、列挙型の呼び出し方法を見ていきましょう!
通常の呼び出し
print(Gender.男性) # Gender.男性
nameのみの呼び出し
print(Gender.男性.name) # 男性
valueのみの呼び出し
print(Gender.男性.value) # 0
valueからの呼び出し
print(Gender(0)) # Gender.男性
for文を使った呼び出し
for g in Gender: print(g) # Gender.男性 # Gender.女性
列挙型の比較
列挙型は比較されることが多いオブジェクトです。
==
print(Gender.男性 == Gender.男性) # True print(Gender.男性 == Gender.女性) # False
!=
print(Gender.男性 != Gender.男性) # False print(Gender.男性 != Gender.女性) # True
is
print(Gender.男性 is Gender.男性) # True print(Gender.男性 is Gender.女性) # False
大なり小なり
print(Gender.男性 < Gender.男性) # TypeError print(Gender.男性 > Gender.女性) # TypeError
IntEnumクラスなら可能。
数値との比較
数値と比較すると False が返される。
print(Gender.男性 == 0) # False print(Gender.女性 == 0) # False
数値と比較したいなら IntEnumクラスを使う。
列挙型のメソッド
列挙型には、通常のクラスと同様にメソッドを定義することもできます。呼び出し時にインスタンス化する必要はありません。
from enum import Enum class Gender(Enum): 男性 = 0 女性 = 1 # 列挙型のメソッド def get_name(self): return self.name print(Gender.男性.get_name()) # 男性 print(Gender.女性.get_name()) # 女性
コンストラクタを定義することもできます。定義した場合は、列挙型の値がインスタンス変数に渡されます。
from enum import Enum class Gender(Enum): 男性 = 0 女性 = 1 # 列挙型のコンストラクタ def __init__(self, num): self.num = num print(Gender.男性.num) # 0 print(Gender.女性.num) # 1
以下のように複数の値でも可能です。
from enum import Enum class Test(Enum): NUMS1 = (0, 1, 2) NUMS2 = (3, 4, 5) def __init__(self, num1, num2, num3): self.num1 = num1 self.num2 = num2 self.num3 = num3 print(Test.NUMS1.num1) # 0 print(Test.NUMS1.num2) # 1 print(Test.NUMS1.num3) # 2 print(Test.NUMS2.num1) # 3 print(Test.NUMS2.num2) # 4 print(Test.NUMS2.num3) # 5
なんかちょっと違和感がありますね...。
整数と比較できる列挙型[IntEnumクラス]
IntEnumクラスは、Enumクラスとあまり違いはありませんが、整数と比較ができるようになっています。
from enum import IntEnum class Gender(IntEnum): 男性 = 0 女性 = 1 print(Gender.男性 == 0) # True print(Gender.女性 == 0) # False
また、異なるIntEnum型とも比較可能です。
from enum import IntEnum class Gender(IntEnum): 男性 = 0 女性 = 1 class Test(IntEnum): NUM1 = 0 NUM2 = 1 print(Gender.男性 == Test.NUM1) # True print(Gender.男性 == Test.NUM2) # False
さらに、Intが頭に付いているだけあって整数として扱える場面が増えています。
print(int(Gender.男性)) # 0 nums = [1, 2, 3] print(nums[Test.NUM1]) # 1 print(abs(Test.NUM1)) # 0
auto
enumモジュールのauto()をvalueに指定することで適切な値を取得できる。
Enum、IntEnumのvalueに指定した場合、最後の値に1を加えたものになる。
from enum import auto, Enum class MyEnum(Enum): name1 = auto() name2 = auto() name3 = auto() print(MyEnum.name1.value) print(MyEnum.name2.value) print(MyEnum.name3.value)
実行結果
1 2 3
初期値を決めたい場合は、最初だけ明示的に値を指定する。
from enum import auto, Enum class MyEnum(Enum): name1 = 100 name2 = auto() name3 = auto() print(MyEnum.name1.value) print(MyEnum.name2.value) print(MyEnum.name3.value)
実行結果
100 101 102
まとめ
この記事では、Pythonの列挙型の使い方について解説しました。
Enumクラスを継承して使う- 整数と比較したい場合は、
IntEnumクラスを使う
列挙型を使うことでマジックナンバーを減らすことができます。使える場面があったらじゃんじゃん使っていきましょう!
また、フラグを扱うためのクラスも Python 3.6 で追加されました。
それでは今回の内容はここまでです!ではまたどこかで〜( ・∀・)ノ
- enum --- 列挙型のサポート


