Python 的原生类型中并不包含枚举类型。为了提供更好的解决方案,Python 通过 PEP 435 在 3.4 版本中添加了 enum 标准库。

官网:https://docs.python.org/3.6/library/enum.html

枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期、月份、状态等。在没有专门提供枚举类型的时候我们是怎么做呢,一般就通过字典或类来实现:

Color = {
 'RED' : 1,
 'GREEN': 2,
 'BLUE' : 3,
}
 
class Color:
 RED = 1
 GREEN = 2
 BLUE = 3

这种来实现枚举如果小心翼翼地使用当然没什么问题,毕竟是一种妥协的解决方案。它的隐患在于可以被修改。更好的方式是使用标准库提供的 Enum 类型,官方库值得信赖。3.4 之前的版本也可以通过 pip install enum 下载支持的库。

enum模块

enum模块定义了:

  • 4种枚举类:Enum, IntEnum, Flag, IntFlag
  • 装饰器:unique()
  • 助手:auto

Flag, IntFlag, auto在python3.6中加入的。

创建枚举

方式一:实例化枚举基类。

from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
print(Month.Apr.value)
for name, member in Month.__members__.items():
    print(name, '=>', member, ',', member.value)
from enum import Enum

colour = Enum('colour',{'red':6, 'green':3, 'blue':5})
print(colour.red.value)
for name,member in colour.__members__.items():
    print(name,'=>', member, ',', member.value)

完整的API如下:
Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>, start=1)

python intenum python intenum库_实例化

方式二:自定义枚举类。自定义枚举类必须继承自一个枚举基类,至多一个具体的数据类型以及0至多个混合类,自定义的枚举类不能实例化。

from enum import Enum
class Color(Enum):
    RED = 2
    GREEN = 3
    BLUE = 6
print(Color.RED.value)

# c = Color() #不能实例化,否则会报错

定义枚举时,成员名称不允许重复  

from enum import Enum

class Color(Enum):
    red = 1
    red = 2

上面的代码,就无法执行。提示错误:TypeError: Attempted to reuse key: 'red'

默认情况下,不同的成员值允许相同。但是两个相同值的成员,第二个成员的名称被视作第一个成员的别名

from enum import Enum

class Color(Enum):
    red = 1
    red_alias = 1

成员Color.red和Color.red_alias具有相同的值,那么成员Color.red_alias的名称red_alias就被视作成员Color.red名称red的别名。

如果枚举中存在相同值的成员,在通过值获取枚举成员时,只能获取到第一个成员

from enum import Enum

class Color(Enum):
    red = 1
    red_alias = 1

print(Color(1))

输出结果为:Color.red

如果要限制定义枚举时,不能定义相同值的成员。可以使用装饰器@unique【要导入unique模块】

from enum import Enum, unique


@unique
class Color(Enum):
    red = 1
    red_alias = 1

 

 

注意点:
1. 枚举值可以是任何类型,如果值不重要可以使用auto()自动选择。但在有其他已定义的值的情况下,谨慎与auto混用
2. Color是枚举类,Color.RED等是枚举成员,枚举成员拥有name和value属性
3. 虽然使用class关键字创建,但枚举并不是常规意义上的python类

对枚举成员及其属性的程序化访问

from enum import Enum
class Color(Enum):
    RED = 2
    GREEN = 3
    BLUE = 6

#查看所有枚举成员
print(list(Color))
for i in Color: #枚举支持按照定义时的顺序进行迭代。
    print(i)

#枚举成员的展现形式,有name属性和value属性
print(Color.BLUE,end='\n'*2)

#查看枚举成员的名称
print(Color.RED.name,end='\n'*2)

#查看枚举成员的值
print(Color.RED.value,end='\n'*2)

#枚举成员的type类型是其所属的枚举类
print(type(Color.BLUE))
print(isinstance(Color.RED, Color),end='\n'*2)

#枚举成员是可哈希的,因此可以在字典和集合中使用
apples = {}
apples[Color.RED] = 'red delicious'
apples[Color.GREEN] = 'granny smith'
print(apples,end='\n'*2)

 通过成员的名称来获取成员

Color['red']

通过成员值来获取成员

Color(2)

 通过成员,来获取它的名称和值

red_member = Color.red
red_member.name
red_member.value

自动生成枚举值

对于不重要的枚举值,可以使用auto自动生成。

from enum import Enum, auto

class Color(Enum):
    RED = auto()
    BLUE = auto()
    GREEN = auto()

auto生成什么值取决于_generate_next_value_()方法,可重写。

from enum import Enum,auto
class AutoName(Enum):
    def _generate_next_value_(name, start, count, last_values):
        return name
class Ordinal(AutoName):
    NORTH = auto()
    SOUTH = auto()
    EAST = auto()

迭代

枚举支持迭代器,可以遍历枚举成员,如果枚举有值重复的成员,循环遍历枚举时只获取值重复成员的第一个成员。

from enum import Enum

class Color(Enum):
    red = 1
    orange = 2
    yellow = 3
    green = 4
    blue = 5
    indigo = 6
    purple = 7
    red_alias = 1

for color in Color:
    print(color)

如果想把值重复的成员也遍历出来,要用枚举的一个特殊属性__members__,__members__属性是一个映射了枚举成员及其名称的有序字典,包括成员别名。

from enum import Enum

class Color(Enum):
    red = 1
    orange = 2
    yellow = 3
    green = 4
    blue = 5
    indigo = 6
    purple = 7
    red_alias = 1

for color in Color.__members__.items():
    print(color)

枚举比较

枚举的成员可以通过 is 同一性比较或通过 == 等值比较。不能进行大小比较。

from enum import Enum
class Color(Enum):
    RED = 2
    GREEN = 3
    BLUE = 6
    red = 2

#身份比较
print(Color.RED is Color.RED)
print(Color.RED is Color.red)
print(Color.RED is Color.BLUE)
print(Color.RED is not Color.BLUE)

#等值比较
print(Color.RED == Color.red)
print(Color.BLUE != Color.red)

#不能进行大小比较,否则报错。
# print(Color.BLUE >= Color.red)

扩展枚举 IntEnum

IntEnum 是 Enum 的扩展,可以枚举成员可以进行比较(实质是枚举成员的值进行比较),不同类型的整数枚举也可以相互比较。

from enum import IntEnum

class Shape(IntEnum):
    red = 1
    green = 2
    blue = 6

class Request(IntEnum):
    RED = 1
    GREEN = 2
    BLUE = 9

print(Shape.red == 1)  # True
print(Shape.green < 3)  # True
print(Shape.blue <= Shape.red) #False

print(Shape.red == Request.RED)  # True
print(Shape.blue >= Request.BLUE)  # False