Python小技巧之枚举类.md

2022/6/13 Python小技巧

# Python小技巧

大家好呀,今天是2021年的最后一天啦!预祝大家元旦快乐的同时,咱们的更新也是不能间断的~于是给大家聊聊新学的知识点: 枚举类.

# 读法

  • 英式英语: 椅娜姆 [ɪˌnjuːm]

  • 美式读音: 饿呢母 ['enəm]

# 枚举的概念

枚举在别的语言中都是很常见的,不知道我当时学Python的时候是不是还没有(也可能我没学到)。先来说说什么是枚举:

在数学和计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。
1

听起来有点晦涩,其实就是列举一组数据的所有可能出现的类型。我们来看一个生动的例子:

  • 东南西北

    在不考虑东北,东南这样的组合方向时,我们其实只有4种方向。

  • 星期

    同理我们来看看星期X,只可能是星期一到星期天,也就是7种数据。

    枚举的意义就是把我们所有可能出现的类型都提前准备好,以备不时之需。理解了概念之后,我们来看一个具体的应用:

# 枚举的应用

假设我们这时候要记录一个物体的朝向,体现在数据库的话,可能会用0,1,2,3代表东南西北。

假设我们判断方向,我们可能这么写:

# 数据库中的Thing(物体对象)
a = Thing()
if a.position == 1:
    print("魔法伤害")
1
2
3
4

大家看看这样的代码,有没有觉得有什么问题?虽然他能很好地运转,但是仔细想想,过1个月,你再来看,你可能不太清楚1代表南方还是北方。

有的导弹鬼会说:东南西北,1肯定是南哦!

是没错,但是你想,你组里来了个新人,人家从小背的就是东西南北。他觉得1是西呢?再或者,有个新人习惯性所有数据从1开始,也就是东南西北分别对应1234

所以这样会给咱们带来一个可读障碍

那我们换成枚举类,会怎么样呢?show you the code!

from enum import Enum

class Position(Enum):
    east = 0
    south = 1
    west = 2
    north = 3

a = Thing()
if a.postion == Postion.south:
    print("魔法伤害")

1
2
3
4
5
6
7
8
9
10
11
12

我们来解析下代码:

  1. 我们引入了Enum类
  2. 定义了一个类并继承自Enum
  3. 里面很简单,定义东南西北,分别为0123

这样写的话,来了新人(再憨憨)也知道你判断的是位置是不是南方

# 存在的问题

但其实这样写是不对的,Enum类只能和Enum类进行比较。我们看看这样的输出:

惊不惊喜,意不意外?没错,枚举类是只能和枚举类比较,那我们怎么解决这个问题呢?

# IntEnum

别担心,除了枚举类,我们还有继承自Enum的IntEnum,我们改改代码:

注意改动处,我们只是换了个父类。

# unique

有的导弹鬼很坏,他问,我可能手滑,复制错了,比如south写成了1,west也写成了1,能不能给我点提示啊?

这并没有报错呀

当然是有的!!!

我们引入unique装饰器,放到枚举类上:

可以看到提醒你2个数据重复啦!!!

# 提高可读性

有人说,这里面定义英文名很难受诶。我就想看东南西北!!!我们可以改写Position的__str__方法,并给个静态方法:

from enum import IntEnum, unique


@unique
class Position(IntEnum):
    east = 0
    south = 1
    west = 2
    north = 3

    def __str__(self):
        if self.value == self.east:
            return "东"
        if self.value == self.south:
            return "南"
        if self.value == self.west:
            return "西"
        if self.value == self.north:
            return "北"
        raise Exception("枚举值错误")

    @property
    def desc(self):
        return self.__str__()


print(Position.east)
print(Position.east.name)
print(Position.east.value)
print(Position.east.desc == "东")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

可以看到,我们新增了__str__和desc方法,其实这里if很多,我们在Python3.10可以替换为switch.

看看执行结果:

# 如果我们想要英文south,就调用name属性,想要数字value就调用value属性,要中文名称调用desc即可。

今天的枚举类就介绍到这里了,大家有兴趣可以看看enum里面的其他东西。祝大家元旦快乐~~