1. enum列舉
列舉是一組符號名稱(列舉成員)的集合,列舉成員應該是唯一的、不可變的,在列舉中,可以對成員進行恒等比較,并且列舉本身是可迭代的,
1.1 創建列舉
可以使用class語法派生Enum并增加描述值的類屬性來定義一個新列舉,
import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 print('\nMember name: {}'.format(BugStatus.wont_fix.name)) print('Member value: {}'.format(BugStatus.wont_fix.value))
決議這個類時,Enum的成員會被轉換為實體,每個實體有一個對應成員名的name屬性,另外有一個value屬性,對應為類定義中的名所賦的值,

1.2 迭代
迭代處理enum類會產生列舉的各個成員,
import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 for status in BugStatus: print('{:15} = {}'.format(status.name, status.value))
這些成員按它們在類定義中宣告的順序生成,不會用名和值來對它們排序,

1.3 比較Enum
由于列舉成員是無序的,所以它們只支持按同一性和相等性進行比較,
import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 actual_state = BugStatus.wont_fix desired_state = BugStatus.fix_released print('Equality:', actual_state == desired_state, actual_state == BugStatus.wont_fix) print('Identity:', actual_state is desired_state, actual_state is BugStatus.wont_fix) print('Ordered by value:') try: print('\n'.join(' ' + s.name for s in sorted(BugStatus))) except TypeError as err: print(' Cannot sort: {}'.format(err))
大于或小于比較符會產生TypeError例外,

有些列舉中的成員要表現得更像數字,例如,要支持比價,對于這些列舉要使用IntEnum類,
import enum class BugStatus(enum.IntEnum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 print('Ordered by value:') print('\n'.join(' ' + s.name for s in sorted(BugStatus)))

1.4 唯一列舉值
有相同值的Enum成員會被處理為同一個成員物件的別名參考,別名可以避免Enum的迭代器中出現重復的值,
import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 by_design = 4 closed = 1 for status in BugStatus: print('{:15} = {}'.format(status.name, status.value)) print('\nSame: by_design is wont_fix: ', BugStatus.by_design is BugStatus.wont_fix) print('Same: closed is fix_released: ', BugStatus.closed is BugStatus.fix_released)
由于by_design和closed是其他成員的別名,迭代處理Enum時它們不會單獨出現在輸出中,一個成員的規范名是與這個值關聯的第一個名字,

如果要求所有成員有唯一的值,則要為Enum增加@unique修飾符,
class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 # This will trigger an error with unique applied. by_design = 4 closed = 1
解釋Enum類時,有重復值的成員會觸發一個ValueError例外,

1.5 通過編程創建列舉
有些情況下,通過編程創建列舉會更方便,而不是在類定義中硬編碼定義列舉,在這些情況下,Enum還支持向類建構式傳遞成員名和值,
import enum BugStatus = enum.Enum( value='BugStatus', names=('fix_released fix_committed in_progress ' 'wont_fix invalid incomplete new'), ) print('Member: {}'.format(BugStatus.new)) print('\nAll members:') for status in BugStatus: print('{:15} = {}'.format(status.name, status.value))
value引數是列舉名,用于構建成員的表示,names引數會列出列舉的成員,傳遞單個字串時,會按空白符和逗號拆分,所得到的token會被用作成員名,這些成員還會自動賦值,從1開始,

要想更多地控制與成員關聯的值,可以把names字串替換為一個由兩部分元組構成的序列或者一個將名映射到值的字典,
import enum BugStatus = enum.Enum( value='BugStatus', names=[ ('new', 7), ('incomplete', 6), ('invalid', 5), ('wont_fix', 4), ('in_progress', 3), ('fix_committed', 2), ('fix_released', 1), ], ) print('All members:') for status in BugStatus: print('{:15} = {}'.format(status.name, status.value))
在這個例子中,指定了一個兩部分元組的串列而不是一個只包含成員名的字串,這樣就可以按enum_create.py中定義的同樣的順序利用成員重新構造BugStatus列舉,

1.6 非整數成員值
Enum成員值并不僅限于整數,任何型別的物件都可以與成員關聯,如果值是一個元組,那么成員會作為單個引數被傳遞到__init__(),
import enum class BugStatus(enum.Enum): new = (7, ['incomplete', 'invalid', 'wont_fix', 'in_progress']) incomplete = (6, ['new', 'wont_fix']) invalid = (5, ['new']) wont_fix = (4, ['new']) in_progress = (3, ['new', 'fix_committed']) fix_committed = (2, ['in_progress', 'fix_released']) fix_released = (1, ['new']) def __init__(self, num, transitions): self.num = num self.transitions = transitions def can_transition(self, new_state): return new_state.name in self.transitions print('Name:', BugStatus.in_progress) print('Value:', BugStatus.in_progress.value) print('Custom attribute:', BugStatus.in_progress.transitions) print('Using attribute:', BugStatus.in_progress.can_transition(BugStatus.new))
在這個例子中,每個成員值分別是一個元組,包括數值ID(如可能存盤在一個資料庫中的ID)和從當前狀態遷移的一個合法變遷串列,

對于更復雜的情況,元組可能變得很難用,因為成員值可以是任意型別的物件,如果對每個enum值都需要跟蹤大量單獨的屬性,那么這些情況下可以使用字典,復雜的值可以直接作為唯一引數傳遞到__init__()而不是self,
import enum class BugStatus(enum.Enum): new = { 'num': 7, 'transitions': [ 'incomplete', 'invalid', 'wont_fix', 'in_progress', ], } incomplete = { 'num': 6, 'transitions': ['new', 'wont_fix'], } invalid = { 'num': 5, 'transitions': ['new'], } wont_fix = { 'num': 4, 'transitions': ['new'], } in_progress = { 'num': 3, 'transitions': ['new', 'fix_committed'], } fix_committed = { 'num': 2, 'transitions': ['in_progress', 'fix_released'], } fix_released = { 'num': 1, 'transitions': ['new'], } def __init__(self, vals): self.num = vals['num'] self.transitions = vals['transitions'] def can_transition(self, new_state): return new_state.name in self.transitions print('Name:', BugStatus.in_progress) print('Value:', BugStatus.in_progress.value) print('Custom attribute:', BugStatus.in_progress.transitions) print('Using attribute:', BugStatus.in_progress.can_transition(BugStatus.new))
這個例子描述了與前例相同的資料,不過使用的是字典而非元組,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/192494.html
標籤:Python
下一篇:python 進制
