Python 的列舉型別
起步
Python 的原生型別中並不包含列舉型別。為了提供更好的解決方案,Python 通過ofollow,noindex" target="_blank">PEP 435
在 3.4 版本中添加了enum
標準庫。
列舉型別可以看作是一種標籤或是一系列常量的集合,通常用於表示某些特定的有限集合,例如星期、月份、狀態等。在沒有專門提供列舉型別的時候我們是怎麼做呢,一般就通過字典或類來實現:
Color = { 'RED': 1, 'GREEN': 2, 'BLUE' : 3, } class Color: RED= 1 GREEN = 2 BLUE= 3
這種來實現列舉如果小心翼翼地使用當然沒什麼問題,畢竟是一種妥協的解決方案。它的隱患在於可以被修改。
使用 Enum
更好的方式是使用標準庫提供的Enum
型別,官方庫值得信賴。3.4 之前的版本也可以通過pip install enum
下載支援的庫。簡單的示例:
from enum import Enum class Color(Enum): red = 1 green = 2 blue = 3
列舉成員有值(預設可重複),列舉成員具有友好的字串表示:
>>> print(Color.red) Color.red >>> print(repr(Color.red)) <Color.red: 1> >>> type(Color.red) <Enum 'Color'> >>> isinstance(Color.green, Color) True
列舉型別不可例項化,不可更改。
定義列舉
定義列舉時,成員名不允許重複
class Color(Enum): red = 1 green = 2 red = 3# TypeError: Attempted to reuse key: 'red'
成員值允許相同,第二個成員的名稱被視作第一個成員的別名
class Color(Enum): red= 1 green = 2 blue= 1 print(Color.red)# Color.red print(Color.blue)# Color.red print(Color.red is Color.blue)# True print(Color(1))# Color.red在通過值獲取列舉成員時,只能獲取到第一個成員
若要不能定義相同的成員值,可以通過 unique 裝飾
from enum import Enum, unique @unique class Color(Enum): red= 1 green = 2 blue= 1# ValueError: duplicate values found in <enum 'Color'>: blue -> red
列舉取值
可以通過成員名來獲取成員也可以通過成員值來獲取成員:
print(Color['red'])# Color.red通過成員名來獲取成員 print(Color(1))# Color.red通過成員值來獲取成員
每個成員都有名稱屬性和值屬性:
member = Color.red print(member.name)# red print(member.value)# 1
支援迭代的方式遍歷成員,按定義的順序,如果有值重複的成員,只獲取重複的第一個成員:
for color in Color: print(color)
特殊屬性__members__
是一個將名稱對映到成員的有序字典,也可以通過它來完成遍歷:
for color in Color.__members__.items(): print(color)# ('red', <Color.red: 1>)
列舉比較
列舉的成員可以通過is
同一性比較或通過==
等值比較:
Color.red is Color.red Color.red is not Color.blue Color.blue == Color.red Color.blue != Color.red
列舉成員不能進行大小比較:
Color.red < Color.blue# TypeError: unorderable types: Color() < Color()
擴充套件列舉 IntEnum
IntEnum
是Enum
的擴充套件,不同型別的整數列舉也可以相互比較:
from enum import IntEnum class Shape(IntEnum): circle = 1 square = 2 class Request(IntEnum): post = 1 get = 2 print(Shape.circle == 1)# True print(Shape.circle < 3)# True print(Shape.circle == Request.post) # True print(Shape.circle >= Request.post) # True