有時候在改code的時候看到一些狀態回傳都使用Enum,一開始覺得理所當然,但直到前陣子看到一些文章在細究Enum才知道原來這個套件真的是妙用之大。
下面有一個簡單的例子,習慣上會把Enum Member Name都寫成全大寫。
from enum import Enum
# 簡單的水果範例
class Fruit(Enum):
APPLE = "Apple"
BANANA = "Banana"
ORANGE = "Orange"
當然,上面舉的範例有夠爛。但這樣上面狀態回傳水果時就可以使用下面的方式直接寫下面這樣
def get_fruit(....)
...
return Fruit.APPLE.name
而工作時,有些同事在Table也只會存取相對應的數字,最後才回到程式中轉換
from enum import Enum
class Status(Enum):
Open = 1
Pending = 2
Close = 3
這樣使用下面的方式就可以直接再轉回狀態了。讓整體狀態方便管理也容易記憶跟撰寫。
from enum import Enum
def process_status(....):
....
return Status(1).name
以為這樣已經夠神奇了,但前陣子看到另外一個更好玩的寫法。下面這種寫法就會直接把數字順序的補下去了。
from enum import Enum, auto
class EmployerNumber(Enum):
ANDY = auto() # 1
SANDY = auto() # 2
WENDY = auto() # 3
CINDY = auto() # 4
MANDY = auto() # 5
print(list(EmployerNumber))
# [<EmployerNumber.Andy: 1>, <EmployerNumber.Sandy: 2>,
# <EmployerNumber.Wendy: 3>, <EmployerNumber.Cindy: 4>,
# <EmployerNumber.Mandy: 5>]
Enum看到現在,轉換也有幾種寫法。看完也是覺得寫法千變萬化。
class EmployerNumber(Enum):
ANDY = auto() # 1
SANDY = auto() # 2
WENDY = auto() # 3
CINDY = auto() # 4
MANDY = auto() # 5
print(EmployerNumber.ANDY.name) # ANDY
print(EmployerNumber['ANDY'].name) # ANDY
print(EmployerNumber(1).name) # ANDY
print(EmployerNumber.SANDY.value) # 2
print(EmployerNumber['SANDY'].value) # 2
print(EmployerNumber(2).value) # 2
若當你確定你的Enum轉出來的Value會是String就可以採用下面寫法,就不用透過value再轉一層,甚至直接可以接String method轉換。(但要3.11之後的版本才能使用)
from enum import StrEnum
class Fruit(StrEnum):
APPLE = "Apple"
BANANA = "Banana"
ORANGE = "Orange"
print(Fruit.APPLE) # Apple
print(Fruit.APPLE.upper()) # APPLE
3.11之前的寫法就可以採用下列
from enum import Enum
class Fruit(str, Enum):
APPLE = "Apple"
BANANA = "Banana"
ORANGE = "Orange"
print(Fruit.APPLE) # Apple
print(Fruit.APPLE.upper()) # APPLE
不像StrEnum,IntEnum不受版本使用限制,也可以很方便的轉換數字
from enum import IntEnum
class EmployerNumber(IntEnum):
ANDY = auto() # 1
SANDY = auto() # 2
WENDY = auto() # 3
CINDY = auto() # 4
MANDY = auto() # 5
print(EmployerNumber.ANDY) # 1
這三者中,前兩者我覺得會是很實用的一些裝飾器的用法,而Global的用法可能就要小心取用。
from enum import Enum, unique
@unique
class Students(Enum):
MANDY = 1
CHARLIE = 1
JOHN = 2
SALLY = 3
SNOOPY = 4
"""ValueError: duplicate values found in <enum 'Students'>: CHARLIE -> MANDY
"""
from enum import Enum, verify, CONTINUOUS
@verify(CONTINUOUS)
class EmployerNumber(Enum):
ANDY = 1
SANDY = 2
CINDY = 4
MANDY = 5
"""ValueError: invalid enum 'EmployerNumber': missing values 3
"""
而Global更為有趣,這樣的裝飾器讓你可以直接呼叫Enum 成員的Name,但這樣用起來可能會有誤用或難以閱讀的狀況,可能都要小心使用。
from enum import Enum, global_enum
@global_enum
class EmployerNumber(Enum):
ANDY = 1
SANDY = 2
CINDY = 4
MANDY = 5
print(ANDY) # ANDY
print(ANDY.value) # 1
感覺Enum還是有很多神奇的用法,就大概看了一些覺得工作上會用到的東西摘出來寫就是。就當作自己工作上跟閱讀上的筆記來做紀錄,也方便之後翻閱時方便找資料。
參考資料:
Enum (枚舉),程式可讀性提高必備技巧
Module enum overview
Python 3 文件