Monors Note

Pythonとそれ以外いろいろ

PythonでのEnumクラスの使用方法

Enum型ってなんのためにあるの状態だったのですが、かなり便利なことに気が付いたのでまとめます。

値クラスの作成をしたはいいが、不具合が多くてもっといい方法はないかを探したのがきっかけです。 (環境はPython 3.5.2です。)

最初に作成した値クラスは以下の通り。

class Pos(object):
    def __init__(self): raise AttributeError('this instance is not able to embody')
        
    NOUN = '名詞'
    VERB = '動詞'
    PARTICLE = '助詞'
    ADJECTIVE = '形容詞'

しかし、この方法では Pos.NOUN = '猫'でクラス属性の書き換えが可能です。 これらをいじって堅牢な定数クラスを作成するのは骨が折れそうです。

Enum型の導入

これら問題を簡単に解決する標準ライブラリがPythonにはあるようです。 また、Effective Javaでも上記の様な型クラスを作成せず、Enum型を使用することが推奨されています。 (項目30: int定数の代わりにenumを使用する)

Enum型を用いる利点

Enum型を用いる利点は以下の通りです。

  • コンパイル時に代入された値に変換されないので、デバック時に分かりやすい。
  • 異なるEnum型を比較しようとするとコンパイルエラーとなる。

Enumの使い方

Python 3.4 から標準ライブラリに入る Enum 型が今からでも便利 - Qiitaを参考に使い方をまとめます。 (IntEnumに関しては省略しています。)

enumモジュール内のEnumクラスを使用します。呼び出し方法は3種類で可能ですが、下記の方法では内部の値が何なのかは覗けません。

from enum import Enum

class Hoo(Enum):
    NOUN = '名詞'
    VERB = '動詞'
    PARTICLE = '助詞'
    ADJECTIVE = '形容詞'
    NOUNS = '名詞'

# 3つの方法でアクセス可能
## 属性
print(Hoo.NOUN ) # Hoo.NOUN

## キーワードを指定した呼び出し
print(Hoo('名詞')) # Hoo.NOUN

## 添え字
print(Hoo['NOUN']) # Hoo.NOUN

値を覗くにはnamevalue属性を使用します。

Hoo.NOUN.name # 名詞

Hoo.NOUN.value # NOUN

値クラスで問題だった値の再代入を行った場合はエラーとなります。

Hoo.NEKO = '猫' # AttributeError: Cannot reassign members.

ただし、同値比較はenum型同士しか行えません。

print(Hoo.NOUN == '名詞') # False
print(Hoo.NOUN == 'NOUN') # False