Python枚举(enum)定义及作用(实例解析)

在以下的文章之中我们来了解一下什么是python中的枚举类。了解一下什么是python枚举类,以及python枚举类在python编程之中能起到什么样的作用。

一. 使用普通类直接实现枚举

在Python中,枚举和我们在对象中定义的类变量时一样的,每一个类变量就是一个枚举项,访问枚举项的方式为:类名加上类变量,像下面这样:

class color():
    YELLOW  = 1
    RED     = 2
    GREEN   = 3
    PINK    = 4
 
# 访问枚举项
print(color.YELLOW) # 1

虽然这样是可以解决问题的,但是并不严谨,也不怎么安全,比如:

1、枚举类中,不应该存在key相同的枚举项(类变量)

2、不允许在类外直接修改枚举项的值

class color():
    YELLOW  = 1
    YELLOW  = 3   # 注意这里又将YELLOW赋值为3,会覆盖前面的1
    RED     = 2
    GREEN   = 3
    PINK    = 4
 
# 访问枚举项
print(color.YELLOW) # 3
 
# 但是可以在外部修改定义的枚举项的值,这是不应该发生的
color.YELLOW = 99
print(color.YELLOW) # 99

. 使用enum模块

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

例子:

from enum import Enum

class Color(Enum):
    red    = 1
    orange = 2
    yellow = 3
    green  = 4
    blue   = 5
    indigo = 6
    purple = 7

print(Color.yellow)        # 打印成员color.yellow
print(type(Color.yellow))  # 
print(Color.yellow.name)   #成员名称yellow 
print(Color.yellow.value)  # 成员值3
print(type(Color.yellow.value)) # 

代码分析:

  1. 上面的代码,我们定义了颜色的枚举Color.
  2. 颜色枚举有7个成员,分别是Color.red、Color.orange、Color.yellow等。
  3. 每一个成员都有它们各自名称和值,Color.red成员的名称是:red,值是:1。
  4. 每个成员的数据类型就是它所属的枚举。

2.1 Enum类是可调用的

>>> Animal = Enum('Animal', 'ANT BEE CAT DOG',module=__name__
)
>>> Animal

>>> Animal.ANT

>>> Animal.ANT.value
1
>>>Animal.DOG.value
4

这样我们就获得了Animal类型的枚举类(value属性则是自动赋给成员的int常量,默认从1开始计数。)

调用的第一个参数Enum是枚举的名称

第二个参数是枚举成员名称的来源

它可以是以空格分隔的名称字符串,名称序列,具有键/值对的2元组序列,或者名称与值的映射(例如字典)。

第三个参数用于指定可以找到新Enum类的模块名称。

#空格分隔的字符串 
'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE'

#序列
['RED', 'GREEN', 'BLUE']

#具有键/值对的2元组序列
[('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)]

#字典
{'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42}

Enum返回一个派生的新类。换句话说,上面的赋值Animal相当于:

>>> class Animal(Enum):
...     ANT = 1
...     BEE = 2
...     CAT = 3
...     DOG = 4
...

2.2枚举支持迭代器,可以遍历枚举成员

from enum import Enum
class Color(Enum):
    red = 1
    orange = 2
    yellow = 3
    green = 4
    blue = 5
    indigo = 6
    purple = 7
    red_alias = 1


#如果枚举有值重复的成员,循环遍历枚举时只获取值重复成员的第一个成员
for color in Color:  
    print(color)
#输出结果是:
#Color.red
#Color.orange
#Color.yellow
#Color.green
#Color.blue
#Color.indigo
#Color.purple
#可以发现Color.red_alias并没有出现在输出结果中。


#如果想把值重复的成员也遍历出来,要用枚举的一个特殊属性__members__
for name, member in Color.__members__.items(): 
    print(name, '=>', member, ',', member.value)
#输出结果是:
#red => Color.red , 1
#orange => Color.orange , 2
#yellow => Color.yellow , 3
#green => Color.green , 4
#blue => Color.blue , 5
#indigo => Color.indigo , 6
#purple => Color.purple , 7
#red_alias => Color.red , 1


#或者
for color in Color.__members__.items():
    print(color)

#输出结果是:
#('red', )
#('orange', )
#('yellow', )
#('green', )
#('blue', )
#('indigo', )
#('purple', )

如果需要更精确地控制枚举类型,可以从Enum派生出自定义类(@unique装饰器可以帮助我们检查保证没有重复值。下面会介绍):

# 导入枚举类
from enum import Enum
 
# 继承枚举类
class color(Enum):
    YELLOW  = 1  # YELLOW的value被设定为1#YELLOW  = 5  #TypeError: Attempted to reuse key: 'YELLOW'  定义枚举时,成员名称不允许重复 
    BEOWN   = 1  # 注意BROWN的值和YELLOW的值相同,这是允许的,此时的BROWN相当于YELLOW的别名
    RED     = 2
    GREEN   = 3
    PINK    = 4
 
class color2(Enum):
    YELLOW  = 1
    RED     = 2
    GREEN   = 3
    PINK    = 4

使用自己定义的枚举类:

print(color.YELLOW) # color.YELLOW
print(type(color.YELLOW)) # 
 
print(color.YELLOW.value)  # 1
print(type(color.YELLOW.value)) # 
 
print(color.YELLOW == 1)    # False
print(color.YELLOW.value == 1)  # True
print(color.YELLOW == color.YELLOW)  # True
print(color.YELLOW == color2.YELLOW)  # False
print(color.YELLOW is color2.YELLOW)  # False
print(color.YELLOW is color.YELLOW)  # True
 
print(color(1))         # color.YELLOW
print(type(color(1)))   # 

print(color['YELLOW'])  # color.YELLOW
print(type(color['YELLOW']))   # 

三.注意事项

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

2、定义枚举时,成员名称不允许重复

from enum import Enum

class Color(Enum):
    red = 1
    red = 2

上面的代码,就无法执行。提示错误:TypeError: Attempted to reuse key: ‘red’

3、枚举类里面定义的Key = Value,在类外部不能修改Value值,也就是说下面这个做法是错误的

color.YELLOW = 2  # Wrong, can't reassign member

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

5、默认情况下,不同的成员值允许相同。但是两个相同值的成员,第二个成员的名称被视作第一个成员的别名

from enum import Enum

class Color(Enum):
    red = 1
    red_alias = 1

成员Color.red和Color.red_alias具有相同的值,那么成员Color.red_alias的名称red_alias就被视作成员Color.red名称red的别名。

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

from enum import IntEnum
class Color(IntEnum):
    YELLOW  = '1'
    RED     = 2
    GREEN   = 3
    PINK    = 4

print(type(Color.YELLOW.value)) # 

7、@unique装饰器可以帮助我们检查保证没有重复值。要导入unique模块

from enum import Enum, unique

class Weekday(Enum):
    Sun = 0 
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 0

@unique
class Weekday2(Enum):
    Sun = 0 
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 0 #ValueError: duplicate values found in : Sat -> Sun

注意:经过unique修饰的Weekday2报错#ValueError: duplicate values found in : Sat -> Sun,因为Sat和Sun值相同,都是0

8、使用自动值

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

>>> from enum import Enum, auto
>>> class Color(Enum):
...     RED = auto()
...     BLUE = auto()
...     GREEN = auto()
...
>>>print(Color.RED.value) 
1
「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论