この記事では、Pythonで列挙型を使う方法を解説します。列挙型(Enum)とは、抽象データを定義するための機能で、性別などのマジックナンバーを使ってしまいそうな値を型として定義することができます。
例えば、以下のようなコードを見たことありませんか?
# 性別を表す変数
gender = 0
if gender == 0:
print('男性')
else:
print('女性')
上記のコードは、gender変数の値が「0ならば男性」「0以外ならば女性」と出力するコードです。しかし、値自体にはなんの関連性も無く、人によっては「0 = 女性」「1 = 男性」「2 = その他」と定義するかもしれません。
そこで列挙型の出番です!
※ Pythonではバージョン3.4から追加されました。
列挙型(Enum)を使う
列挙型は、enumモジュールのEnumクラスを継承させたクラスを定義することで使うことができます。先ほどの性別を列挙型にすると以下のようになります。
from enum import Enum
class Gender(Enum):
男性 = 0
女性 = 1
※ 今回は分かりやすいように日本語で定義しました。
これでGenderという性別を表す列挙型が定義できました。
次に、この列挙型を用いてクラスを作成してみましょう!以下のコードでは、Personという人の情報を持つクラスを作成し、インスタンス変数に先ほどの列挙型を指定しています。
class Person:
def __init__(self, name, age, gender):
self.name = name # 名前
self.age = age # 年齢
self.gender = gender # 性別
# インスタンス変数の出力
def print_args(self):
print(self.name)
print(self.age)
# 性別の判定
if self.gender == Gender.男性:
print('男性')
else:
print('女性')
# Genderを使うことで男性と女性という2つのデータから選ぶことができる
p = Person('碇シンジ', 14, Gender.男性)
p.print_args()
# 碇シンジ
# 14
# 男性
性別を列挙型で定義したことで、Personクラスのgender変数をマジックナンバーを使わずに定義できました。このように、列挙型を使うことで性別という抽象的な概念も型として定義することができます。
定義
列挙型は以下のように定義します。
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
is not
print(Gender.男性 is not Gender.男性)
# False
print(Gender.男性 is not Gender.女性)
# True
大なり小なり
print(Gender.男性 < Gender.男性) # エラー
print(Gender.男性 > Gender.女性) # エラー
数値との比較
数値と比較したいならIntEnumクラスを使う必要があります。
print(Gender.男性 == 0)
# False
print(Gender.女性 == 0)
# False
メソッド
通常のクラスと同様に列挙型にはメソッドを定義することもできます。呼び出し時にインスタンス化する必要はありません。
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
def get_num(self):
return self.num
print(Gender.男性.get_num())
# 0
以下のように複数の値でも可能です。
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
def get_nums(self):
return self.num1, self.num2, self.num3
print(Test.NUMS1.get_nums())
# (0, 1, 2)
print(Test.NUMS2.get_nums())
# (3, 4, 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
まとめ
この記事では、Pythonの列挙型の使い方について解説しました。
- Enumクラスを継承して使う
- 整数と比較したい場合はIntEnumクラスを使う
列挙型を使うことでマジックナンバーを減らすことができます。使える場面があったらじゃんじゃん使っていきましょう!
それでは今回の内容はここまでです!ではまたどこかで〜( ・∀・)ノ