【Python】列挙型を使おう! 【Enum・IntEnum】

Python

この記事では、Pythonで列挙型を使う方法を解説します。

列挙型(Enum)とは、抽象データを定義するための機能で、性別などのマジックナンバーを使ってしまいそうな値を型として定義することができます。

例えば、以下のようなコードを見たことありませんか?

# 性別を表す変数
gender = 0

if gender == 0:
    print('男性')
else:
    print('女性')

上記のコードは、gender変数の値が「0ならば男性」「0以外ならば女性」と出力するコードです。しかし、値自体にはなんの関連性も無く、人によっては「0 = 女性」「1 = 男性」「2 = その他」と定義するかもしれません。

そこで列挙型の出番です!
※ Pythonではバージョン3.4から追加されました。

列挙型(Enum)を使う

列挙型は、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クラスを使う

列挙型を使うことでマジックナンバーを減らすことができます。使える場面があったらじゃんじゃん使っていきましょう!

それでは今回の内容はここまでです!ではまたどこかで〜( ・∀・)ノ

タイトルとURLをコピーしました