我主要是c#开发人员,但我目前正在用Python开发一个项目。

我如何在Python中表示等价的Enum ?


当前回答

我喜欢Java枚举,这就是我在Python中的做法:

def enum(clsdef):
    class Enum(object):
        __slots__=tuple([var for var in clsdef.__dict__ if isinstance((getattr(clsdef, var)), tuple) and not var.startswith('__')])

        def __new__(cls, *args, **kwargs):
            if not '_the_instance' in cls.__dict__:
                cls._the_instance = object.__new__(cls, *args, **kwargs)
            return cls._the_instance

        def __init__(self):
            clsdef.values=lambda cls, e=Enum: e.values()
            clsdef.valueOf=lambda cls, n, e=self: e.valueOf(n)
            for ordinal, key in enumerate(self.__class__.__slots__):
                args=getattr(clsdef, key)
                instance=clsdef(*args)
                instance._name=key
                instance._ordinal=ordinal
                setattr(self, key, instance)

        @classmethod
        def values(cls):
            if not hasattr(cls, '_values'):
                cls._values=[getattr(cls, name) for name in cls.__slots__]
            return cls._values

        def valueOf(self, name):
            return getattr(self, name)

        def __repr__(self):
            return ''.join(['<class Enum (', clsdef.__name__, ') at ', str(hex(id(self))), '>'])

    return Enum()

示例使用:

i=2
@enum
class Test(object):
    A=("a",1)
    B=("b",)
    C=("c",2)
    D=tuple()
    E=("e",3)

    while True:
        try:
            F, G, H, I, J, K, L, M, N, O=[tuple() for _ in range(i)]
            break;
        except ValueError:
            i+=1

    def __init__(self, name="default", aparam=0):
        self.name=name
        self.avalue=aparam

所有类变量都定义为元组,就像构造函数一样。到目前为止,还不能使用命名参数。

其他回答

Enum类可以是一行程序。

class Enum(tuple): __getattr__ = tuple.index

如何使用它(正向和反向查找、键、值、项等)

>>> State = Enum(['Unclaimed', 'Claimed'])
>>> State.Claimed
1
>>> State[1]
'Claimed'
>>> State
('Unclaimed', 'Claimed')
>>> range(len(State))
[0, 1]
>>> [(k, State[k]) for k in range(len(State))]
[(0, 'Unclaimed'), (1, 'Claimed')]
>>> [(k, getattr(State, k)) for k in State]
[('Unclaimed', 0), ('Claimed', 1)]

嗯…我认为最接近枚举的应该是字典,定义如下:

months = {
    'January': 1,
    'February': 2,
    ...
}

or

months = dict(
    January=1,
    February=2,
    ...
)

然后,你可以像这样使用常量的符号名:

mymonth = months['January']

还有其他选项,如元组列表或元组的元组,但字典是唯一提供“符号”(常量字符串)方式来访问 价值。

编辑:我也喜欢亚历山大的答案!

如果你需要数值,这是最快的方法:

dog, cat, rabbit = range(3)

在Python 3中。X你也可以在最后添加一个星号占位符,它将吸收范围内所有剩余的值,以防你不介意浪费内存和无法计数:

dog, cat, rabbit, horse, *_ = range(100)

我通常使用的解决方案是这个简单的函数来获取动态创建的类的实例。

def enum(names):
    "Create a simple enumeration having similarities to C."
    return type('enum', (), dict(map(reversed, enumerate(
        names.replace(',', ' ').split())), __slots__=()))()

使用它非常简单,只需使用包含想要引用的名称的字符串调用函数即可。

grade = enum('A B C D F')
state = enum('awake, sleeping, dead')

这些值只是整数,因此如果需要可以利用它(就像在C语言中一样)。

>>> grade.A
0
>>> grade.B
1
>>> grade.F == 4
True
>>> state.dead == 2
True

在答案列表中没有看到这个,这是我想出的一个。它允许使用'in'关键字和len()方法:

class EnumTypeError(TypeError):
    pass

class Enum(object):
    """
    Minics enum type from different languages
    Usage:
    Letters = Enum(list('abc'))
    a = Letters.a
    print(a in Letters) # True
    print(54 in Letters) # False
    """
    def __init__(self, enums):
        if isinstance(enums, dict):
            self.__dict__.update(enums)
        elif isinstance(enums, list) or isinstance(enums, tuple):
            self.__dict__.update(**dict((v,k) for k,v in enumerate(enums)))
        else:
            raise EnumTypeError

    def __contains__(self, key):
        return key in self.__dict__.values()

    def __len__(self):
        return len(self.__dict__.values())


if __name__ == '__main__':
    print('Using a dictionary to create Enum:')
    Letters = Enum(dict((v,k) for k,v in enumerate(list('abcde'))))
    a = Letters.a
    print('\tIs a in e?', a in Letters)
    print('\tIs 54 in e?', 54 in Letters)
    print('\tLength of Letters enum:', len(Letters))

    print('\nUsing a list to create Enum:')
    Letters = Enum(list('abcde'))
    a = Letters.a
    print('\tIs a in e?', a in Letters)
    print('\tIs 54 in e?', 54 in Letters)
    print('\tLength of Letters enum:', len(Letters))

    try:
        # make sure we raise an exception if we pass an invalid arg
        Failure = Enum('This is a Failure')
        print('Failure')
    except EnumTypeError:
        print('Success!')

输出:

Using a dictionary to create Enum:
        Is a in e? True
        Is 54 in e? False
        Length of Letters enum: 5

Using a list to create Enum:
        Is a in e? True
        Is 54 in e? False
        Length of Letters enum: 5
Success!