Enum 枚举是一组绑定到唯一值的符号名称, 类似于全局变量。
枚举定义
创建一个 Enum 就是简单地写一个继承 Enum 的类,再确定好枚举成员即可。
from enum import Enum
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
添加行为
可以通过添加行为,查看当天是周几。
import datetime
from enum import Enum
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
@classmethod
def from_date(cls, date):
return cls(datetime.date.isoweekday(date))
print(Weekday.from_date(datetime.date.today())) # Weekday.TUESDAY
枚举合并
Flag 支持将多个枚举值进行合并。
from enum import Enum, Flag
class Weekday(Flag):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 4
THURSDAY = 8
FRIDAY = 16
SATURDAY = 32
SUNDAY = 64
# 对于不存在的枚举值,会用已有的枚举值组合展示
print(Weekday(7)) # Weekday.MONDAY|TUESDAY|WEDNESDAY
print(Weekday.MONDAY | Weekday.TUESDAY) # Weekday.MONDAY|TUESDAY
成员访问
from enum import Enum
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
print(Weekday(3)) # Weekday.WEDNESDAY
print(Weekday.MONDAY) # Weekday.MONDAY
print(Weekday.MONDAY.name) # MONDAY
print(Weekday.MONDAY.value) # 1
print(type(Weekday.MONDAY.name)) # <class 'str'>
print(type(Weekday.MONDAY.value)) # <class 'int'>
print(Weekday["MONDAY"]) # Weekday.MONDAY
重复名称和值
枚举名称不能重复
from enum import Enum
class Weekday(Enum):
MONDAY = 1
MONDAY = 2 # TypeError: 'MONDAY' already defined as 1
枚举值可以重复
from enum import Enum
class Weekday(Enum):
MONDAY = 1
ALIAS_FOR_MONDAY = 1
如果要限制枚举值也不能重复,可使用 unique 装饰器。
from enum import Enum, unique
@unique
class Weekday(Enum):
MONDAY = 1
ALIAS_FOR_MONDAY = 1 # ValueError: duplicate values found in <enum 'Weekday'>: ALIAS_FOR_MONDAY -> MONDAY
自动设定值
默认从 1 开始递增
from enum import Enum, unique, auto
class AutoName(Enum):
pass
# @staticmethod
# def _generate_next_value_(name, start, count, last_values):
# return name
class Ordinal(AutoName):
NORTH = auto()
SOUTH = auto()
EAST = auto()
WEST = auto()
print([member.value for member in Ordinal]) # [1, 2, 3, 4]
自定义自动设定值
from enum import Enum, unique, auto
class AutoName(Enum):
@staticmethod
def _generate_next_value_(name, start, count, last_values):
return f"TEST_{name}"
class Ordinal(AutoName):
NORTH = auto()
SOUTH = auto()
EAST = auto()
WEST = auto()
print([member.value for member in Ordinal]) # ['TEST_NORTH', 'TEST_SOUTH', 'TEST_EAST', 'TEST_WEST']
迭代遍历
from enum import Enum, Flag
class Weekday(Flag):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 4
THURSDAY = 8
FRIDAY = 16
SATURDAY = 32
SUNDAY = 64
ALIAS_FOR_SUNDAY = 64
print(list(Weekday)) # [<Weekday.MONDAY: 1>, <Weekday.TUESDAY: 2>, <Weekday.WEDNESDAY: 4>, <Weekday.THURSDAY: 8>, <Weekday.FRIDAY: 16>, <Weekday.SATURDAY: 32>, <Weekday.SUNDAY: 64>]
for name, member in Weekday.__members__.items():
print(name, member)
# MONDAY Weekday.MONDAY
# TUESDAY Weekday.TUESDAY
# WEDNESDAY Weekday.WEDNESDAY
# THURSDAY Weekday.THURSDAY
# FRIDAY Weekday.FRIDAY
# SATURDAY Weekday.SATURDAY
# SUNDAY Weekday.SUNDAY
# ALIAS_FOR_SUNDAY Weekday.SUNDAY
比较运算
枚举值之间无法进行有序的比较。
from enum import Enum, Flag
class Weekday(Flag):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 4
THURSDAY = 8
FRIDAY = 16
SATURDAY = 32
SUNDAY = 64
ALIAS_FOR_SUNDAY = 64
print(Weekday.MONDAY is Weekday.MONDAY) # True
print(Weekday.MONDAY is Weekday.SUNDAY) # False
print(Weekday.MONDAY is not Weekday.SUNDAY) # True
print(Weekday.MONDAY == Weekday.MONDAY) # True
print(Weekday.MONDAY == 1) # False
print(Weekday.MONDAY != Weekday.MONDAY) # False
print(Weekday.MONDAY < Weekday.TUESDAY) # TypeError: '<' not supported between instances of 'Weekday' and 'Weekday'
子类化
正常子类化
from enum import Enum
class Color(Enum):
pass
class MoreColor(Color):
PINK = 17
如果定义了任何成员时,枚举类则不允许被子类化。
from enum import Enum
class Color(Enum):
RED = 1
class MoreColor(Color): # TypeError: <enum 'MoreColor'> cannot extend <enum 'Color'>
PINK = 17
派生枚举
IntEnum
IntEnum 的成员可与整数进行比较;不同类型的整数枚举也可以相互进行比较。
from enum import IntEnum
class Shape(IntEnum):
CIRCLE = 1
SQUARE = 2
class Request(IntEnum):
POST = 1
GET = 2
print(Shape == 1) # False
print(Shape.CIRCLE == 1) # True
print(Shape.CIRCLE == Request.POST) # True
StrEnum
StrEnum 的成员可与字符串进行比较;不同类型的字符串枚举也可以相互进行比较。
from enum import StrEnum
class Shape(StrEnum):
CIRCLE = "circle"
SQUARE = "square"
print(Shape.CIRCLE == "circle") # True
IntFlag
IntFlag 成员可以用位运算符 (&, |, ^, ~) 进行组合并且如果可能的话其结果仍将是 IntFlag 成员。 与 IntEnum 类似。
from enum import IntFlag
class Perm(IntFlag):
R = 4
W = 2
X = 1
RWX = R | W | X
print(Perm.R | Perm.W) # 6
print(Perm.R + Perm.W) # 6
RW = Perm.R | Perm.W
print(Perm.R in RW) # True
print(RW - Perm.W) # 4
print(Perm.R == 4) # True
print(Perm.RWX) # 7
print(list(Perm)) # [<Perm.R: 4>, <Perm.W: 2>, <Perm.X: 1>]
print(~Perm.X) # 6
print(Perm.R in Perm.RWX) # True