22

Python 3.4 には、新しい enum モジュールと Enum データ型があります。まだ 3.4 に切り替えることができない場合は、Enum がバックポートされています。

Enum メンバーは docstring をサポートしているため、ほとんどすべての python オブジェクトがそうであるように、それらを設定したいと思います。それを行う簡単な方法はありますか?

4

2 に答える 2

9

はい、これまでのところ私のお気に入りのレシピです。おまけとして、整数値を指定する必要もありません。次に例を示します。

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

于 2013-10-12T04:13:49.737 に答える