Python 标准库之 Enum 枚举

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值