Python学习之路——枚举类

前言:

首先大家要明白的是:枚举类不是Python的原生类!不是原生类!不是!Python中的枚举类是依靠 enum模块 来实现的。
枚举是在 Python3.4 添加的新功能(安装Python解释器后自带的官方模块),3.4以前的版本需要使用pip install enum来安装模块后使用。

一、枚举

什么是枚举?

枚举可看作是一系列符号名称的集合,集合中每一个元素要保证唯一性和不可变(与字典类似)。因此我们可以对枚举中元素进行恒等比较,通俗来讲枚举就是一系列常量的集合,枚举是可迭代的。

枚举的作用

首先我们先思考一下,在 Python中我们如何定义常量?

我们最常用的做法是采用变量名大写的方式来定义常量。

这种方式虽然简单,但问题在于我们定义的仍然是变量、是可以被修改的,而常量是什么呢?简单来说就是不可变的量。

枚举就有不可变的特性,因此枚举的主要作用就来定义常量

二、代码实现

enum 库中定义了四个枚举类,它们是可被用来定义名称和值的不重复集合: Enum, IntEnum, Flag 和 IntFlag。 此外还定义了一个装饰器 unique() 和一个辅助类 auto

名称 功能
Enum 创建枚举常量
IntEnum 创建属于 int 的子类的枚举常量
IntFlag 创建可使用按位运算符进行组合而不会丢失其 IntFlag 成员资格的枚举常量。 IntFlag 成员同样也是 int 的子类
Flag 创建可使用按位运算符进行组合而不会丢失其 Flag 成员资格的枚举常量
unique() 确保只将一个名称绑定到任意一个值
auto 实例会被替换为一个可作为 Enum 成员的适当的值。 初始值从 1 开始

1. Enum类

继承Enum类进行创建:

from enum import Enum

class Color(Enum):
    BLACK = '#000000'
    RED = '#FF0000'
    GREEN = '#00FF00'
    BLUE = '#0000FF'
    WHITE = '#FFFFFF'


print(Color)    # <enum 'Color'>
print(Color.RED)    # Color.RED
print(Color.BLACK.name)    # BLACK
print(Color.GREEN.value)    # #00FF00

枚举类中不允许有同名的枚举成员,当定义两个同名枚举成员时就会抛出错误:

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

Animal()
# TypeError: Attempted to reuse key: 'CAT'

直接使用Enum进行创建:

from enum import Enum

Animal = Enum('Animal', 'ANT BEE CAT DOG')
print(Animal)    # <enum 'Animal'>
print(Animal.ANT)    # <Animal.ANT>
print(Animal.ANT.value)   # 1

Enum 传入的第一参数是枚举的名称,第二个参数是枚举成员名称的 来源。 它可以是一个用空格分隔的名称字符串、名称序列、键/值对 2 元组的序列,或者名称到值的映射(例如字典)。

最后两种选项使得可以为枚举任意赋值;其他选项会自动以从 1 开始递增的整数赋值(使用 start 形参可指定不同的起始值)。

枚举类可以直接使用 for语句进行遍历:

from enum import Enum

Animal = Enum('Animal', 'ANT BEE CAT DOG')
for i in Animal:
    print(i, '*', i.name, '*', i.value)
'''
Animal.ANT * ANT * 1
Animal.BEE * BEE * 2
Animal.CAT * CAT * 3
Animal.DOG * DOG * 4
'''

枚举成员之间可以使用 is 和 ==、!=进行比较,但不能使用< 、>、>=、<=进行比较。

from enum import Enum

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


print(Animal.CAT == Animal.DOG)    # False
print(Animal.CAT is Animal.DOG)    # False

2. IntEnum类

IntEmum 的用法与 Enum 类似,但是 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

不过,它们仍然不可与标准 Enum 枚举进行比较:

class Shape(IntEnum):
    CIRCLE = 1
    SQUARE = 2

class Color(Enum):
    RED = 1
    GREEN = 2

print(Shape.CIRCLE == Color.RED)    # False

3. IntFlag类

IntFlag 类同样是基于 int 的,不同之处在于 IntFlag 成员可使用按位运算符 &, |, ^, ~ 进行组合且结果仍然为 IntFlag 成员。
正如名称所表明的,IntFlag 成员同时也是 int 的子类,并能在任何使用 int 的场合被使用。 IntFlag 成员进行除按位运算以外的其他运算都将导致失去 IntFlag 成员资格。

from enum import IntFlag

class Perm(IntFlag):
    R = 4
    W = 2
    X = 1

print(Perm.R | Perm.W)    # Perm.R|W
print(Perm.R + Perm.W)    # 6
RW = Perm.R | Perm.W
print(Perm.R in RW)    # True
print(Perm.R | 8)    # Perm.8|R

4. Flag类

与 IntFlag 类似,Flag 成员可使用按位运算符 (&, |, ^, ~) 进行组合,与 IntFlag 不同的是它们不可与任何其它 Flag 枚举或 int 进行组合或比较。 虽然可以直接指定值,但推荐使用 auto 作为值以便让 Flag 选择适当的值。

from enum import Flag, auto

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

print(Color.RED & Color.GREEN)    # Color.0
print(bool(Color.RED & Color.GREEN))    # False

5. unique装饰器

默认情况下,枚举允许有多个名称作为某个相同值的别名。 如果不想要这样的行为,可以使用 unique 装饰器来确保每个值在枚举中只被使用一次:

from enum import Enum, unique

@unique
class Mistake(Enum):
    ONE = 1
    TWO = 2
    THREE = 3
    FOUR = 3
# ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE

6. auto函数

如果确切的值不重要,你可以使用 auto:

from enum import Enum, auto
class Color(Enum):
    RED = auto()
    BLUE = auto()
    GREEN = auto()

print(list(Color))
# [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

三、官方文档

有关 Enum模块 的更多信息可以参考官方文档:官方文档

猜你喜欢

转载自blog.csdn.net/qq_43580193/article/details/105004431
今日推荐