协慌网

登录 贡献 社区

我怎样才能用 Python 代表'Enum'?

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

我怎样才能在 Python 中表示 Enum 的等价物?

答案

PEP 435 中所述,已将枚举添加到 Python 3.4 中。在 pypi 上它也被反向移植到 3.3,3.2,3.1,2.7,2.6,2.5 和 2.4

对于更高级的枚举技术尝试aenum 库 (2.7,3.3+,同一作者的enum34 ,代码不 PY2 和 PY3 之间的完美兼容,比如你需要__order__在 Python 2 )。

  • 要使用enum34 ,请执行$ pip install enum34
  • 要使用aenum ,请执行$ pip install aenum

安装enum (无数字)将安装完全不同且不兼容的版本。


from enum import Enum     # for enum34, or the stdlib version
# from aenum import Enum  # for the aenum version
Animal = Enum('Animal', 'ant bee cat dog')

Animal.ant  # returns <Animal.ant: 1>
Animal['ant']  # returns <Animal.ant: 1> (string lookup)
Animal.ant.name  # returns 'ant' (inverse lookup)

或等效地:

class Animal(Enum):
    ant = 1
    bee = 2
    cat = 3
    dog = 4

在早期版本中,完成枚举的一种方法是:

def enum(**enums):
    return type('Enum', (), enums)

使用方式如下:

>>> Numbers = enum(ONE=1, TWO=2, THREE='three')
>>> Numbers.ONE
1
>>> Numbers.TWO
2
>>> Numbers.THREE
'three'

您还可以使用以下内容轻松支持自动枚举:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    return type('Enum', (), enums)

并使用如下:

>>> Numbers = enum('ZERO', 'ONE', 'TWO')
>>> Numbers.ZERO
0
>>> Numbers.ONE
1

可以通过以下方式添加对将值转换回名称的支持:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    reverse = dict((value, key) for key, value in enums.iteritems())
    enums['reverse_mapping'] = reverse
    return type('Enum', (), enums)

这将覆盖具有该名称的任何内容,但它对于在输出中呈现您的枚举非常有用。如果反向映射不存在,它将抛出 KeyError。第一个例子:

>>> Numbers.reverse_mapping['three']
'THREE'

在 PEP 435 之前,Python 没有等效的,但你可以实现自己的。

我自己,我喜欢保持简单(我在网上看过一些非常复杂的例子),像这样......

class Animal:
    DOG = 1
    CAT = 2

x = Animal.DOG

在 Python 3.4( PEP 435 )中,您可以将Enum作为基类。这为您提供了一些额外的功能,如 PEP 中所述。例如,枚举成员与整数不同,它们由namevalue

class Animal(Enum):
    DOG = 1
    CAT = 2

print(Animal.DOG)
# <Animal.DOG: 1>

print(Animal.DOG.value)
# 1

print(Animal.DOG.name)
# "DOG"

如果您不想键入值,请使用以下快捷方式:

class Animal(Enum):
    DOG, CAT = range(2)

Enum实现可以转换为列表并且可以迭代 。其成员的顺序是声明顺序,与其值无关。例如:

class Animal(Enum):
    DOG = 1
    CAT = 2
    COW = 0

list(Animal)
# [<Animal.DOG: 1>, <Animal.CAT: 2>, <Animal.COW: 0>]

[animal.value for animal in Animal]
# [1, 2, 0]

Animal.CAT in Animal
# True

这是一个实现:

class Enum(set):
    def __getattr__(self, name):
        if name in self:
            return name
        raise AttributeError

这是它的用法:

Animals = Enum(["DOG", "CAT", "HORSE"])

print(Animals.DOG)