Python中的枚举数据类型(Enum)

Python中的枚举数据类型

枚举的字面含义是指列出有穷集合中的所有元素,即一一列举的意思。在Python中,枚举可以视为是一种数据类型,当一个变量的取值只有几种有限的情况时,我们可以将其声明为枚举类型。例如表示周几的这一变量weekday,只有七种可能的取值,我们就可以将其声明为枚举类型。

那么枚举的类型该如何实现呢? 我们一个很直观的想法是:可以通过类的方式来实现,变量就是类,变量所有可能的取值作为类的变量。之后访问的时候,通过类名+变量名的方式就可以进行访问:

class Weekday():
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7

print(Weekday.wednesday)    #  3

但是这样实现枚举类型的方式存在一定的问题:

1、枚举的枚举项不能出现重复,即key不应该相同(以上例来讲,不能出现两个wednesday)

2、枚举项的值不应该允许在外部进行修改(枚举类型一般是固定下来的常量,声明好之后不能在外部随意更改)

如下所示:

class Weekday():
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7
    wednesday = 333

print(Weekday.wednesday)    #  333
Weekday.wednesday = "星期三"
print(Weekday.wednesday)    #  星期三

为了解决上述两个问题,我们可以使用Python中提供的enum模块。

enum的使用

enum模块是系统内置模块,可以直接使用import导入,但是在导入的时候,不建议使用import enum将enum模块中的所有数据都导入,一般使用的最多的就是enum模块中的Enum、IntEnum、unique这几项。

借助enum模块,我们在实现上述需求的时候,就可以这样来做:

from enum import Enum
class Weekday(Enum):
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7

print(Weekday.wednesday)         # Weekday.wednesday      
print(type(Weekday.wednesday))   # <enum 'Weekday'>
print(Weekday.wednesday.name)    # wednesday
print(Weekday.wednesday.value)   # 3

我们自定义的枚举类型继承Enum基类,之后还是通过Weekday.wednesday获取得到的是枚举成员,通过.name和.value可以获得枚举成员对应的属性。

这时,如果我们在Weekday类中,声明重复的枚举成员,会产生错误:

TypeError: Attempted to reuse key: 'wednesday'

如果在外部进行枚举成员属性值的修改,也会产生错误:

AttributeError: Cannot reassign members.

这样的话,就解决之前存在的两个问题。

此外,对于枚举成员,.name和.value是其内置属性,我们还可以给枚举成员增加其他属性。实现的方式如下:

from enum import Enum
class Weekday(Enum):
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7

Weekday.wednesday.label = "星期三"
Weekday.wednesday.work = "完成假期作业"
Weekday.wednesday.time = 10


print(Weekday.wednesday.label)   # 星期三
print(Weekday.wednesday.work)    # 完成假期作业
print(Weekday.wednesday.time)    # 10

在获取枚举类型的成员时,我们可以通过类名+key的方式实现,即上面的Weekday.wednesday。此外,通过key获取枚举成员的时候,还可以使用Weekday['key']这样的方式。

也可以通过value来获取枚举成员,通过value获取枚举成员是:Weekday(value)这样的方式。

如下所示:

from enum import Enum
class Weekday(Enum):
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7

Weekday.wednesday.label = "星期三"
Weekday.wednesday.work = "完成假期作业"
Weekday.wednesday.time = 10

obj_1 = Weekday.wednesday
print(obj_1.label)             # 星期三

obj_2 = Weekday['wednesday']
print(obj_1.label)             # 星期三

obj_3 = Weekday(3)
print(obj_3.label)             # 星期三

enum的总结

1、枚举类不能用来实例化对象

例如下面的用法是错误的:

from enum import Enum
class Weekday(Enum):
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7

w = Weekday()
print(w.wednesday)

2、访问枚举类中的某个枚举成员,可以有三种方式,详见上面使用部分的介绍。

3、枚举类里面定义的 key = value,在类外部不能修改value值,详见上面使用部分的介绍。

4、枚举成员可以用来比较,使用==或者is。

from enum import Enum
class Weekday(Enum):
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7

obj_1 = Weekday.wednesday

obj_2 = Weekday['wednesday']

obj_3 = Weekday(3)

print(obj_1==obj_2==obj_3)      # True

print(obj_1 is obj_2 is obj_3)  # True

5、继承Enum基类之后,一个枚举类中的key和value,key不能相同,但是value可以相同。

from enum import Enum
class Weekday(Enum):
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7
    test = 3


print(Weekday.test.value)    # 3

如果想让value也不相同的话,可以导入unique。如下所示:

from enum import Enum, unique
@unique
class Weekday(Enum):
    monday = 1
    tuesday = 2
    wednesday = 3
    thirsday = 4
    friday = 5
    saturday = 6
    sunday = 7
    test = 3


print(Weekday.test.value)    # 3

此时的代码会报如下错误:

6、如果要枚举类中的Value只能是整型数字,那么,可以导入IntEnum,然后继承IntEnum即可。注意,此时,如果value为字符串的数字,也不会报错。

参考资料

1、https://www.cnblogs.com/-beyond/p/9777329.html

2、https://docs.python.org/zh-cn/3/library/enum.html

猜你喜欢

转载自blog.csdn.net/ProQianXiao/article/details/113481092