2009年10月19日

PythonでEnum型してみた


PythonでEnumを書いてみた人がいたので、ちょっと考えてみた。


Enumって型の種類なんで、Enum型というものをまず定義せにゃならんのじゃないかと。
ってことは、メタクラスの出番ですね。分かります。


使い方は、doctestのサンプルの通り。
StandardEnumを継承したclass宣言内で、列挙します。
Pythonは識別子だけのステートメントなんて持ってないので、値は明示的に指定しましょう:-)



# -*- coding:utf-8 -*-
"""
>>> class SampleEnum(StandardEnum):
... A = 1
... B = 2
... C = 3
...
>>> SampleEnum.A
<SampleEnum.A value=1>
>>> for e in SampleEnum:
... print e
...
<SampleEnum.A value=1>
<SampleEnum.B value=2>
<SampleEnum.C value=3>
>>> SampleEnum.A == SampleEnum.A
True
>>> SampleEnum.A == SampleEnum.B
False
"""


class EnumType(type):

def __init__(cls, name, bases, dct):
super(EnumType, cls).__init__(name, bases, dct)
cls._values = []

for key, value in dct.iteritems():
if not key.startswith('_'):
v = cls(key, value)
setattr(cls, key, v)
cls._values.append(v)

def __iter__(cls):
return iter(cls._values)


class StandardEnum(object):

__metaclass__ = EnumType

def __init__(self, k, v):
self.v = v
self.k = k

def __repr__(self):
return "<%s.%s value=%s>" % (self.__class__.__name__, self.k, self.v)


if __name__ == '__main__':
import doctest
doctest.testmod()


定義順を保ために、_valuesを使ってるけど、実際のところ値を使った方が、直感的かもしれない。ふつうは昇順に定義するだろうしね。