enum
--- 對列舉的支援¶
在 3.4 版被加入.
原始碼:Lib/enum.py
Important
本頁包含 API 的參考資訊。關於教學資訊及更多進階主題的討論請參考
列舉:
是一組綁定唯一值的代表名稱(成員)
可以用疊代的方式以定義的順序回傳其正式 (canonical)(即非別名)成員
使用call 語法來透過值回傳成員
使用index 語法來透過名稱回傳成員
列舉透過class
語法或函式呼叫的語法來建立:
>>>fromenumimportEnum>>># class 語法>>>classColor(Enum):...RED=1...GREEN=2...BLUE=3>>># 函式語法>>>Color=Enum('Color',[('RED',1),('GREEN',2),('BLUE',3)])
雖然我們可以用class
語法來建立列舉,列舉並不是標準的 Python 類別。參考列舉有何差異以取得更多細節。
備註
命名方式
Color
類別是一個列舉(或enum)Color.RED
、Color.GREEN
等屬性是列舉成員(或成員),並且使用上可以看作常數。列舉成員有名稱和值(
Color.RED
的名稱是RED
,Color.BLUE
的值是3
諸如此類)
模組內容¶
Enum 及其子類別的
type
。用來建立列舉常數的基礎類別。
用來建立列舉常數的基礎類別,可以使用位元操作來結合成員且其結果不失去
Flag
的成員資格。一個有
CONTINUOUS
、NAMED_FLAGS
及UNIQUE
這些值的列舉,和verify()
一起使用來確保給定的列舉符合多種限制。一個有
STRICT
、CONFORM
、EJECT
及KEEP
這些值的列舉,允許列舉對如何處理非法值做更細微的控制。列舉成員的實例會被取代成合適的值。
StrEnum
預設是小寫版本的成員名稱,其它列舉則預設是 1 且往後遞增。允許
Enum
成員擁有屬性且不會與成員名稱有衝突。value
及name
屬性是用這個方式來實作。Enum 類別的裝飾器,用來確保任何值只有綁定到一個名稱上。
Enum 類別的裝飾器,用來檢查列舉上使用者所選的限制。
讓
obj
變成成員。可以當作裝飾器使用。不讓
obj
變成成員。可以當作裝飾器使用。回傳旗標 (flag) 裡包含的所有 2 的次方的整數串列。
在 3.6 版被加入:Flag
,IntFlag
,auto
在 3.11 版被加入:StrEnum
,EnumCheck
,ReprEnum
,FlagBoundary
,property
,member
,nonmember
,global_enum
,show_flag_values
在 3.13 版被加入:EnumDict
資料型別¶
- classenum.EnumType¶
EnumType 是enum 列舉的metaclass。EnumType 可以有子類別 -- 細節請參考建立 EnumType 的子類別。
EnumType
負責在最後的列舉上面設定正確的__repr__()
、__str__()
、__format__()
及__reduce__()
方法,以及建立列舉成員、正確處理重複、提供列舉類別的疊代等等。- __call__(cls,value,names=None,*,module=None,qualname=None,type=None,start=1,boundary=None)¶
這個方法可以用兩種不同的方式呼叫:
查詢已存在的成員:
- cls:
所呼叫的列舉類別。
- value:
要查詢的值。
使用
cls
列舉來建立新列舉(只有在現有列舉沒有任何成員時)
- __contains__(cls,member)¶
如果 member 屬於
cls
則回傳True
:>>>some_var=Color.RED>>>some_varinColorTrue>>>Color.RED.valueinColorTrue
在 3.12 版的變更:在 Python 3.12 之前,如果用非列舉成員做屬於檢查 (containment check) 會引發
TypeError
。- __dir__(cls)¶
回傳
['__class__','__doc__','__members__','__module__']
及cls 的成員名稱:>>>dir(Color)['BLUE', 'GREEN', 'RED', '__class__', '__contains__', '__doc__', '__getitem__', '__init_subclass__', '__iter__', '__len__', '__members__', '__module__', '__name__', '__qualname__']
- __iter__(cls)¶
以定義的順序回傳在cls 中的每個成員:
>>>list(Color)[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]
- __len__(cls)¶
回傳cls 的成員數量:
>>>len(Color)3
- __members__¶
回傳每個列舉名稱到其成員的對映,包括別名
- __reversed__(cls)¶
以跟定義相反的順序回傳cls 的每個成員:
>>>list(reversed(Color))[<Color.BLUE: 3>, <Color.GREEN: 2>, <Color.RED: 1>]
- _add_value_alias_()¶
新增一個值作為現有成員的別名。如果該值已與不同成員連結,則會引發
ValueError
。
在 3.11 版被加入:在 3.11 之前,
EnumType
稱作EnumMeta
,其目前仍可作為別名使用。
- classenum.Enum¶
Enum 是所有enum 列舉的基礎類別。
- name¶
用來定義
Enum
成員的名稱:>>>Color.BLUE.name'BLUE'
- _name_¶
成員名稱。
- _order_¶
已不再使用,只為了向後相容而保留(類別屬性,在類別建立時移除)
- _ignore_¶
_ignore_
只有在建立的時候用到,在列舉建立完成後會被移除。_ignore_
是一個不會變成成員的名稱串列,在列舉建立完成後其名稱會被移除。範例請參考TimePeriod。
- __dir__(self)¶
回傳
['__class__','__doc__','__module__','name','value']
及任何self.__class__ 上定義的公開方法:>>>fromdatetimeimportdate>>>classWeekday(Enum):...MONDAY=1...TUESDAY=2...WEDNESDAY=3...THURSDAY=4...FRIDAY=5...SATURDAY=6...SUNDAY=7...@classmethod...deftoday(cls):...print('today is%s'%cls(date.today().isoweekday()).name)...>>>dir(Weekday.SATURDAY)['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'today', 'value']
- _generate_next_value_(name,start,count,last_values)¶
- name:
定義的成員名稱(例如 'RED')。
- start:
列舉的開始值,預設為 1。
- count:
已定義的成員數量,不包含目前這一個。
- last_values:
一個之前值的串列。
一個staticmethod,用來決定
auto
下一個要回傳的值的:>>>fromenumimportauto>>>classPowersOfThree(Enum):...@staticmethod...def_generate_next_value_(name,start,count,last_values):...return3**(count+1)...FIRST=auto()...SECOND=auto()...>>>PowersOfThree.SECOND.value9
- __init__(self,*args,**kwds)¶
預設情況下,不執行任何操作。如果在成員賦值中給出多個值,這些值將成為與
__init__
分別的引數;例如>>>fromenumimportEnum>>>classWeekday(Enum):...MONDAY=1,'Mon'
Weekday.__init__()
將被稱為Weekday.__init__(self,1,'Mon')
- __init_subclass__(cls,**kwds)¶
一個classmethod,用來進一步設定後續的子類別,預設不做任何事。
- _missing_(cls,value)¶
一個classmethod,用來查詢在cls 裡找不到的值。預設不做任何事,但可以被覆寫以實作客製化的搜尋行為:
>>>fromenumimportStrEnum>>>classBuild(StrEnum):...DEBUG=auto()...OPTIMIZED=auto()...@classmethod...def_missing_(cls,value):...value=value.lower()...formemberincls:...ifmember.value==value:...returnmember...returnNone...>>>Build.DEBUG.value'debug'>>>Build('deBUG')<Build.DEBUG: 'debug'>
- __new__(cls,*args,**kwds)¶
預設情況下不存在。如果有指定,無論是在列舉類別定義中還是在 mixin 類別中(例如
int
),都將傳遞成員賦值中給出的所有值;例如>>>fromenumimportEnum>>>classMyIntEnum(int,Enum):...TWENTYSIX='1a',16
會產生呼叫
int('1a',16)
而該成員的值為26
。備註
當寫自訂的
__new__
時,不要使用super().__new__
,而是要呼叫適當的__new__
。
- __repr__(self)¶
回傳呼叫repr() 時使用的字串。預設回傳Enum 名稱、成員名稱及值,但可以被覆寫:
>>>classOtherStyle(Enum):...ALTERNATE=auto()...OTHER=auto()...SOMETHING_ELSE=auto()...def__repr__(self):...cls_name=self.__class__.__name__...returnf'{cls_name}.{self.name}'...>>>OtherStyle.ALTERNATE,str(OtherStyle.ALTERNATE),f"{OtherStyle.ALTERNATE}"(OtherStyle.ALTERNATE, 'OtherStyle.ALTERNATE', 'OtherStyle.ALTERNATE')
- __str__(self)¶
回傳呼叫str() 時使用的字串。預設回傳Enum 名稱及成員名稱,但可以被覆寫:
>>>classOtherStyle(Enum):...ALTERNATE=auto()...OTHER=auto()...SOMETHING_ELSE=auto()...def__str__(self):...returnf'{self.name}'...>>>OtherStyle.ALTERNATE,str(OtherStyle.ALTERNATE),f"{OtherStyle.ALTERNATE}"(<OtherStyle.ALTERNATE: 1>, 'ALTERNATE', 'ALTERNATE')
- __format__(self)¶
回傳呼叫format() 及f-string 時使用的字串。預設回傳
__str__()
的回傳值,但可以被覆寫:>>>classOtherStyle(Enum):...ALTERNATE=auto()...OTHER=auto()...SOMETHING_ELSE=auto()...def__format__(self,spec):...returnf'{self.name}'...>>>OtherStyle.ALTERNATE,str(OtherStyle.ALTERNATE),f"{OtherStyle.ALTERNATE}"(<OtherStyle.ALTERNATE: 1>, 'OtherStyle.ALTERNATE', 'ALTERNATE')
在 3.12 版的變更:新增Dataclass support
- classenum.IntEnum¶
IntEnum 和
Enum
一樣,但其成員同時也是整數而可以被用在任何使用整數的地方。如果IntEnum 成員經過任何整數運算,結果值會失去其列舉狀態。>>>fromenumimportIntEnum>>>classNumber(IntEnum):...ONE=1...TWO=2...THREE=3...>>>Number.THREE<Number.THREE: 3>>>>Number.ONE+Number.TWO3>>>Number.THREE+58>>>Number.THREE==3True
在 3.11 版的變更:為了更好地支援現存常數取代 (replacement of existing constants) 的使用情境,
__str__()
現在會是int.__str__()
。為了同樣的理由,__format__()
已經是int.__format__()
。
- classenum.StrEnum¶
StrEnum
和Enum
一樣,但其成員同時也是字串而可以被用在幾乎所有使用字串的地方。StrEnum 成員經過任何字串操作的結果會不再是列舉的一部份。備註
stdlib 裡有些地方會檢查只能是
str
而不是str
的子類別(也就是type(unknown)==str
而不是isinstance(unknown,str)
),在這些地方你需要使用str(StrEnum.member)
。備註
為了更好地支援現存常數取代 (replacement of existing constants) 的使用情境,
__str__()
現在會是str.__str__()
。為了同樣的理由,__format__()
也會是str.__format__()
。在 3.11 版被加入.
- classenum.Flag¶
Flag
與Enum
相同,但其成員支援位元運算子&
(AND)、|
(OR)、^
(XOR) 和~
(INVERT);這些操作的結果是列舉的成員(的別名)。- __contains__(self,value)¶
如果 value 在 self 裡則回傳True:
>>>fromenumimportFlag,auto>>>classColor(Flag):...RED=auto()...GREEN=auto()...BLUE=auto()...>>>purple=Color.RED|Color.BLUE>>>white=Color.RED|Color.GREEN|Color.BLUE>>>Color.GREENinpurpleFalse>>>Color.GREENinwhiteTrue>>>purpleinwhiteTrue>>>whiteinpurpleFalse
- __iter__(self):
回傳所有包含的非別名成員:
>>>list(Color.RED)[<Color.RED: 1>]>>>list(purple)[<Color.RED: 1>, <Color.BLUE: 4>]
在 3.11 版被加入.
- __len__(self):
回傳旗標裡的成員數量:
>>>len(Color.GREEN)1>>>len(white)3
在 3.11 版被加入.
- __bool__(self):
如果成員在旗標裡則回傳True,否則回傳False:
>>>bool(Color.GREEN)True>>>bool(white)True>>>black=Color(0)>>>bool(black)False
- __or__(self,other)¶
回傳和 other 做 OR 過後的二進位旗標:
>>>Color.RED|Color.GREEN<Color.RED|GREEN: 3>
- __and__(self,other)¶
回傳和 other 做 AND 過後的二進位旗標:
>>>purple&white<Color.RED|BLUE: 5>>>>purple&Color.GREEN<Color: 0>
- __xor__(self,other)¶
回傳和 other 做 XOR 過後的二進位旗標:
>>>purple^white<Color.GREEN: 2>>>>purple^Color.GREEN<Color.RED|GREEN|BLUE: 7>
- __invert__(self):
回傳所有在type(self) 但不在self 裡的旗標:
>>>~white<Color: 0>>>>~purple<Color.GREEN: 2>>>>~Color.RED<Color.GREEN|BLUE: 6>
在 3.11 版的變更:值為 0 的旗標的repr() 已改變。現在是:
>>>Color(0)<Color: 0>
- classenum.IntFlag¶
IntFlag
和Flag
一樣,但其成員同時也是整數而可以被用在任何使用整數的地方。>>>fromenumimportIntFlag,auto>>>classColor(IntFlag):...RED=auto()...GREEN=auto()...BLUE=auto()...>>>Color.RED&2<Color: 0>>>>Color.RED|2<Color.RED|GREEN: 3>
如果IntFlag 成員經過任何整數運算,其結果不是IntFlag:
>>>Color.RED+23
如果IntFlag 成員經過
Flag
操作且:結果是合法的IntFlag:回傳IntFlag
結果不是合法的IntFlag:結果會根據
FlagBoundary
的設定
未命名且值為 0 的旗標的
repr()
已改變。現在是:>>>Color(0)<Color: 0>
在 3.11 版的變更:為了更好地支援現存常數取代 (replacement of existing constants) 的使用情境,
__str__()
現在會是int.__str__()
。為了同樣的理由,__format__()
已經是int.__format__()
。IntFlag
的反轉 (inversion) 現在會回傳正值,該值是不在給定旗標的所有旗標聯集,而不是一個負值。這符合現有Flag
的行為。
- classenum.ReprEnum¶
ReprEnum
使用Enum
的repr()
,但使用混合資料型別的str()
:繼承
ReprEnum
來保留混合資料型別的str()
/format()
,而不是使用Enum
預設的str()
。在 3.11 版被加入.
- classenum.EnumCheck¶
EnumCheck 包含
verify()
裝飾器使用的選項,以確保多樣的限制,不符合限制會產生ValueError
。- UNIQUE¶
確保每個值只有一個名稱:
>>>fromenumimportEnum,verify,UNIQUE>>>@verify(UNIQUE)...classColor(Enum):...RED=1...GREEN=2...BLUE=3...CRIMSON=1Traceback (most recent call last):...ValueError:aliases found in <enum 'Color'>: CRIMSON -> RED
- CONTINUOUS¶
確保在最小值成員跟最大值成員間沒有缺少值:
>>>fromenumimportEnum,verify,CONTINUOUS>>>@verify(CONTINUOUS)...classColor(Enum):...RED=1...GREEN=2...BLUE=5Traceback (most recent call last):...ValueError:invalid enum 'Color': missing values 3, 4
- NAMED_FLAGS¶
確保任何旗標群組 / 遮罩只包含命名旗標 -- 當值是用指定而不是透過
auto()
產生時是很實用的:>>>fromenumimportFlag,verify,NAMED_FLAGS>>>@verify(NAMED_FLAGS)...classColor(Flag):...RED=1...GREEN=2...BLUE=4...WHITE=15...NEON=31Traceback (most recent call last):...ValueError:invalid Flag 'Color': aliases WHITE and NEON are missing combined values of 0x18 [use enum.show_flag_values(value) for details]
備註
CONTINUOUS 和 NAMED_FLAGS 是設計用來運作在整數值的成員上。
在 3.11 版被加入.
- classenum.FlagBoundary¶
FlagBoundary
控制在Flag
及其子類別中如何處理範圍外的值。- STRICT¶
範圍外的值會引發
ValueError
。這是Flag
的預設行為:>>>fromenumimportFlag,STRICT,auto>>>classStrictFlag(Flag,boundary=STRICT):...RED=auto()...GREEN=auto()...BLUE=auto()...>>>StrictFlag(2**2+2**4)Traceback (most recent call last):...ValueError:<flag 'StrictFlag'> invalid value 20 given 0b0 10100 allowed 0b0 00111
- CONFORM¶
會移除範圍外的值中的非法值,留下合法的
Flag
值:>>>fromenumimportFlag,CONFORM,auto>>>classConformFlag(Flag,boundary=CONFORM):...RED=auto()...GREEN=auto()...BLUE=auto()...>>>ConformFlag(2**2+2**4)<ConformFlag.BLUE: 4>
- EJECT¶
>>>fromenumimportFlag,EJECT,auto>>>classEjectFlag(Flag,boundary=EJECT):...RED=auto()...GREEN=auto()...BLUE=auto()...>>>EjectFlag(2**2+2**4)20
- KEEP¶
範圍外的值會被保留,
Flag
成員資格也會被保留。這是IntFlag
的預設行為:>>>fromenumimportFlag,KEEP,auto>>>classKeepFlag(Flag,boundary=KEEP):...RED=auto()...GREEN=auto()...BLUE=auto()...>>>KeepFlag(2**2+2**4)<KeepFlag.BLUE|16: 20>
在 3.11 版被加入.
- classenum.EnumDict¶
EnumDict 是
dict
的子類別,用來作為定義列舉類別的命名空間(參見Preparing the class namespace)。它被公開來使得EnumType
的子類別能具有進階行為,例如讓每個成員有多個值。它應該在被呼叫時帶上正在建立的列舉類別名稱,否則私有名稱和內部類別將無法被正確處理。注意只有
MutableMapping
介面(__setitem__()
和update()
)被覆寫。可能可以使用其他dict
操作來繞過檢查,例如|=
。- member_names¶
一個成員名稱的串列。
在 3.13 版被加入.
支援的__dunder__
名稱¶
__members__
是一個唯讀有序的成員名稱
:成員
項目的對映。只有在類別上可用。
__new__()
,如果有指定,它必須建立並回傳列舉成員;適當地設定成員的_value_
也是一個很好的主意。一旦所有成員都建立之後就不會再被用到。
支援的_sunder_
名稱¶
_add_alias_()
-- 新增一個名稱作為現有成員的別名。_add_value_alias_()
-- 新增一個值作為現有成員的別名。_name_
-- 成員名稱_value_
-- 成員的值;可以在__new__
設定_missing_()
-- 當值沒有被找到時會使用的查詢函式;可以被覆寫_order_
-- 不再被使用,僅為了向後相容而保留(類別屬性,在類別建立時移除)_generate_next_value_()
-- 用來為列舉成員取得合適的值;可以被覆寫雖然
_sunder_
名稱通常保留用於Enum
類別的進一步開發而不能被使用,但有些是明確允許的:_repr_*
(例如_repr_html_
),例如用於IPython 的豐富顯示
在 3.6 版被加入:_missing_
、_order_
、_generate_next_value_
在 3.7 版被加入:_ignore_
在 3.13 版被加入:_add_alias_
、_add_value_alias_
、_repr_*
通用項目與裝飾器¶
- classenum.auto¶
auto 可以用來取代給值。如果使用的話,Enum 系統會呼叫
Enum
的_generate_next_value_()
來取得合適的值。對Enum
和IntEnum
來說,合適的值是最後一個值加一;對Flag
和IntFlag
來說,是第一個比最大值還大的 2 的次方的數字;對StrEnum
來說,是成員名稱的小寫版本。如果混用auto() 和手動指定值的話要特別注意。auto 實例只有在最上層的賦值時才會被解析:
FIRST=auto()
可以運作(auto() 會被取代成1
)SECOND=auto(),-2
可以運作(auto 會被取代成2
, 因此2,-2
會被用來建立列舉成員SECOND
;THREE=[auto(),-3]
無法運作(<auto實例>,-3
會被用來建立列舉成員THREE
)
在 3.11.1 版的變更:在之前的版本中,
auto()
必須是賦值行裡的唯一內容才能運作正確。可以覆寫
_generate_next_value_
來客製auto 使用的值。備註
在 3.13 預設
_generate_next_value_
總是回傳最大的成員值加一,如果任何成員是不相容的型別就會失敗。
- @enum.property¶
和內建的property 相似的裝飾器,但只專門針對列舉。它允許成員屬性和成員本身有相同名稱。
備註
屬性和成員必須定義在分開的類別裡;例如value 和name 屬性定義在Enum 類別而Enum 子類別可以定義成員名稱為
value
和name
。在 3.11 版被加入.
- @enum.unique¶
專門針對列舉的
class
裝飾器。它搜尋列舉的__members__
,蒐集任何它找到的別名;如果有找到任何別名則引發ValueError
並附上細節:>>>fromenumimportEnum,unique>>>@unique...classMistake(Enum):...ONE=1...TWO=2...THREE=3...FOUR=3...Traceback (most recent call last):...ValueError:duplicate values found in <enum 'Mistake'>: FOUR -> THREE
- @enum.member¶
列舉所使用的裝飾器:其目標會變成成員。
在 3.11 版被加入.
- @enum.nonmember¶
列舉所使用的裝飾器:其目標不會變成成員。
在 3.11 版被加入.
- @enum.global_enum¶
修改列舉的
str()
及repr()
的裝飾器,讓成員顯示為屬於模組而不是其類別。應該只有當列舉成員被匯出到模組的全域命名空間才使用(範例請參考re.RegexFlag
)。在 3.11 版被加入.
- enum.show_flag_values(value)¶
回傳在旗標值中包含的所有 2 的次方的整數串列。
在 3.11 版被加入.
備註¶
這三種列舉型別是設計來直接取代現有以整數及字串為基底的值;因此它們有額外的限制:
__str__
使用值而不是列舉成員的名稱
__format__
因為使用__str__
,也會使用值而不是列舉成員的名稱如果你不需要或不想要這些限制,你可以透過混合
int
或str
型別來建立自己的基礎類別:>>>fromenumimportEnum>>>classMyIntEnum(int,Enum):...pass或者你也可以在你的列舉重新給定合適的
str()
:>>>fromenumimportEnum,IntEnum>>>classMyIntEnum(IntEnum):...__str__=Enum.__str__