Python 枚举 类型详解
一、枚举的优势:
Python 的原生类型中并不包含枚举类型。为了提供更好的解决方案,Python 通过在 3.4 版本中添加了enum
标准库。 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合。
枚举类可以方便地表示星期,月份等常数类型
,如果你不用枚举类,那么你只能用数字或者字符串。如果你使用数字,用1-7来表示星期数,但一个数字在程序中不仅可以表示星期数,可能还有其他许多含义,这样你在写程序时就必须时刻记住这些数字的含义,这降低了程序的可读性,也导致容易出错
。而当你使用字符串时,虽然没有明显的缺点,但在内存中字符串所占内存要比数字多,这就降低了程序的效率
。
枚举类正好弥补了这两方面的缺点,你可以在代码中使用枚举类,但在内存中存放时使用的是数字,既提高了可读性,又提高了程序效率。更重要的是,Python中的枚举类型是不可变类型,又可以进行迭代,这就意味着你可以随时使用枚举类型而不用担心改变了枚举类型的值。
-
在没有专门提供枚举类型的时候我们是怎么做呢,一般就通过字典或类来实现:
Fruit = { 'APPLE' : 1, 'BANANA': 2, 'ORANGE' : 3, } class Fruit: APPLE = 1 BANANA = 2 ORANGE = 3
使用这种存在的隐患就是可能随时被修改。
-
以下操作都是在python 3.5版本。
二、使用Enum:
安装命令:pip install enum
下载库。
简单栗子:
# 导入Enum类
from enum import Enum
class Fruit(Enum):
APPLE = 1
BANANA = 2
ORANGE = 3
print(Fruit.APPLE) # 输出结果: Fruit.APPLE
print(repr(Fruit.APPLE)) # 输出结果:<Fruit.APPLE: 1>
print(type(Fruit.APPLE)) # 输出结果:<enum 'Fruit'>
isinstance(Fruit.APPLE, Fruit) # 输出结果:True
注意:枚举类型不可实例化,不可更改
三、定义枚举:
定义枚举时,成员名不允许重复
class Fruit(Enum):
APPLE = 1
BANANA = 2
BANANA = 3
# 报错信息:TypeError: Attempted to reuse key: 'BANANA'
成员值允许相同,第二个成员的名称被视作第一个成员的别名
class Fruit(Enum):
APPLE = 1
BANBANA = 2
ORANGE = 1
print(Fruit.APPLE) # 输出结果:Fruit.APPLE
print(Fruit.ORANGE) # 输出结果:Fruit.APPLE, 可以看出值相同,第二个成员名视作第一个成员别名
print(Fruit.APPLE is Fruit.ORANGE) # 输出结果:True
print(Fruit(1)) # 输出结果:Fruit.APPLE 通过值获取枚举成员时,只能获取道第一个成员
若不能定义相同成员值,可以通过unique装饰
from enum import Enum, unique
@unique
class Fruit(Enum):
APPLE = 1
BANANA = 2
ORANGE = 1
# 设置了相同的值, APPLE 、ORANGE
# 就会报错:ValueError: duplicate values found in <enum 'Fruit'>: ORANGE -> APPLE
四、枚举取值:
通过成员名称
来获取成员:
print(Fruit['APPLE']) # 输出结果:Fruit.APPLE
通过成员值
来获取成员:
print(Fruit(1)) # 输出结果Fruit.APPLE
成员的名称属性和值属性
:
print(Fruit.APPLE.name) # 输出结果:APPLE,获取名称属性
print(Fruit.APPLE.value) # 输出结果:1 ,获取值的属性
支持迭代方式遍历成员,按定义的顺序,如果有值重复的成员,仅获取重复的第一个成员:
for fruit in Fruit:
print(fruit)
# 输出结果如下:
Fruit.APPLE
Fruit.BANANA
Fruit.ORANGE
特殊属性 __members__
是一个将名称映射到成员的有序字典,也可以通过它来完成遍历:
for fruit in Fruit.__members__.items():
print(fruit)
# 输出结果如下:
('APPLE', <Fruit.APPLE: 1>)
('BANANA', <Fruit.BANANA: 2>)
('ORANGE', <Fruit.ORANGE: 3>)
五、枚举比较:
枚举的成员可以通过 is
同一性比较或通过 ==
等值比较:
Fruit.APPLE is Fruit.ORANGE # 输出结果:False
Fruit.APPLE is not Fruit.ORANGE # 输出结果:True
Fruit.APPLE == Fruit.ORANGE # 输出结果:False
Fruit.APPLE != Fruit.ORANGE # 输出结果:True
枚举成员不能进行大小的比较:
Fruit.APPLE < Fruit.ORANGE
# 输出结果:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: Fruit() < Fruit()
六、枚举 IntEnum类型:
IntEnum
是 Enum
的扩展,不同类型的整数枚举也可以相互比较:
from enum import IntEnum
class Fruit(IntEnum):
APPLE = 1
BANABNA = 2
print(Fruit.APPLE == 1) # 输出结果:True
print(Fruit.APPLE < 2) #输出结果:True
- 使用IntEnum类型,可以进行大小的比较,前提必须是INT类型。
成员值的类型,不可以设置非INT类型:
class Fruit(IntEnum):
APPLE = 1
BANABNA = "2"
ORANGE = 3
print(Fruit.BANANA)
# 输出结果如下:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\Python35\lib\enum.py", line 268, in __getattr__
raise AttributeError(name) from None
AttributeError: BANANA