Python 3.4 には、新しい enum モジュールと Enum データ型があります。まだ 3.4 に切り替えることができない場合は、Enum がバックポートされています。
Enum メンバーは docstring をサポートしているため、ほとんどすべての python オブジェクトがそうであるように、それらを設定したいと思います。それを行う簡単な方法はありますか?
Python 3.4 には、新しい enum モジュールと Enum データ型があります。まだ 3.4 に切り替えることができない場合は、Enum がバックポートされています。
Enum メンバーは docstring をサポートしているため、ほとんどすべての python オブジェクトがそうであるように、それらを設定したいと思います。それを行う簡単な方法はありますか?
はい、これまでのところ私のお気に入りのレシピです。おまけとして、整数値を指定する必要もありません。次に例を示します。
class AddressSegment(AutoEnum):
misc = "not currently tracked"
ordinal = "N S E W NE NW SE SW"
secondary = "apt bldg floor etc"
street = "st ave blvd etc"
"N S E W NE NW SE SW"
の値だけを持っていない理由を尋ねるかもしれませんordinal
。その repr を<AddressSegment.ordinal: 'N S E W NE NW SE SW'>
取得すると、表示が少しぎこちなくなりますが、docstring でその情報をすぐに利用できるようにすることは、良い妥協点です。
Enum のレシピは次のとおりです。
class AutoEnum(enum.Enum):
"""
Automatically numbers enum members starting from 1.
Includes support for a custom docstring per member.
"""
#
def __new__(cls, *args):
"""Ignores arguments (will be handled in __init__."""
value = len(cls) + 1
obj = object.__new__(cls)
obj._value_ = value
return obj
#
def __init__(self, *args):
"""Can handle 0 or 1 argument; more requires a custom __init__.
0 = auto-number w/o docstring
1 = auto-number w/ docstring
2+ = needs custom __init__
"""
if len(args) == 1 and isinstance(args[0], (str, unicode)):
self.__doc__ = args[0]
elif args:
raise TypeError('%s not dealt with -- need custom __init__' % (args,))
そして使用中:
>>> list(AddressSegment)
[<AddressSegment.ordinal: 1>, <AddressSegment.secondary: 2>, <AddressSegment.misc: 3>, <AddressSegment.street: 4>]
>>> AddressSegment.secondary
<AddressSegment.secondary: 2>
>>> AddressSegment.secondary.__doc__
'apt bldg floor etc'
引数を in__init__
ではなくin で処理する理由は、さらに拡張したい場合に__new__
サブクラス化を容易にするためです。AutoEnum