enum
--- 對列舉的支援¶
在 3.4 版被加入.
原始碼:Lib/enum.py
列舉:
是一組綁定唯一值的代表名稱(成員)
可以用疊代的方式以定義的順序回傳其正式 (canonical)(即非別名)成員
使用 call 語法來透過值回傳成員
使用 index 語法來透過名稱回傳成員
列舉透過 class
語法或函式呼叫的語法來建立:
>>> from enum import Enum
>>> # class syntax
>>> class Color(Enum):
... RED = 1
... GREEN = 2
... BLUE = 3
>>> # functional syntax
>>> 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
資料型別¶
- class enum.EnumType¶
EnumType 是列舉的 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_var in Color True >>> Color.RED.value in Color True
在 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>]
在 3.11 版被加入: 在 3.11 之前,
enum
使用EnumMeta
類型,目前保留此類型當作別名。
- class enum.Enum¶
Enum 是所有 enum 列舉的基礎類別。
- name¶
用來定義
Enum
成員的名稱:>>> Color.BLUE.name 'BLUE'
- value¶
Enum
成員給定的值:>>> Color.RED.value 1
成員的值,可以在
__new__()
設定。備註
列舉成員的值
成員的值可以是任何值:
int
、str
等等。如果實際使用什麼值並不重要,你可以使用auto
實例,它會為你選擇合適的值。更多細節請參考auto
。While mutable/unhashable values, such as
dict
,list
or a mutabledataclass
, can be used, they will have a quadratic performance impact during creation relative to the total number of mutable/unhashable values in the enum.
- _name_¶
成員名稱。
- _order_¶
已不再使用,只為了向後相容而保留(類別屬性,在類別建立時移除)
- _ignore_¶
_ignore_
只有在建立的時候用到,在列舉建立完成後會被移除。_ignore_
是一個不會變成成員的名稱串列,在列舉建立完成後其名稱會被移除。範例請參考 TimePeriod。
- __dir__(self)¶
回傳
['__class__', '__doc__', '__module__', 'name', 'value']
及任何 self.__class__ 上定義的公開方法:>>> from datetime import date >>> class Weekday(Enum): ... MONDAY = 1 ... TUESDAY = 2 ... WEDNESDAY = 3 ... THURSDAY = 4 ... FRIDAY = 5 ... SATURDAY = 6 ... SUNDAY = 7 ... @classmethod ... def today(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
下一個要回傳的值的:>>> from enum import auto >>> class PowersOfThree(Enum): ... @staticmethod ... def _generate_next_value_(name, start, count, last_values): ... return 3 ** (count + 1) ... FIRST = auto() ... SECOND = auto() ... >>> PowersOfThree.SECOND.value 9
- __init__(self, *args, **kwds)¶
預設情況下,不執行任何操作。如果在成員賦值中給出多個值,這些值將成為與
__init__
分別的引數;例如>>> from enum import Enum >>> class Weekday(Enum): ... MONDAY = 1, 'Mon'
Weekday.__init__()
將被稱為Weekday.__init__(self, 1, 'Mon')
- __init_subclass__(cls, **kwds)¶
一個 classmethod,用來進一步設定後續的子類別,預設不做任何事。
- _missing_(cls, value)¶
一個 classmethod,用來查詢在 cls 裡找不到的值。預設不做任何事,但可以被覆寫以實作客製化的搜尋行為:
>>> from enum import StrEnum >>> class Build(StrEnum): ... DEBUG = auto() ... OPTIMIZED = auto() ... @classmethod ... def _missing_(cls, value): ... value = value.lower() ... for member in cls: ... if member.value == value: ... return member ... return None ... >>> Build.DEBUG.value 'debug' >>> Build('deBUG') <Build.DEBUG: 'debug'>
- __new__(cls, *args, **kwds)¶
預設情況下不存在。如果有指定,無論是在列舉類別定義中還是在 mixin 類別中(例如
int
),都將傳遞成員賦值中給出的所有值;例如>>> from enum import Enum >>> class MyIntEnum(int, Enum): ... TWENTYSIX = '1a', 16
results in the call
int('1a', 16)
and a value of26
for the member.備註
當寫自訂的
__new__
時,不要使用super().__new__
,而是要呼叫適當的__new__
。
- __repr__(self)¶
回傳呼叫 repr() 時使用的字串。預設回傳 Enum 名稱、成員名稱及值,但可以被覆寫:
>>> class OtherStyle(Enum): ... ALTERNATE = auto() ... OTHER = auto() ... SOMETHING_ELSE = auto() ... def __repr__(self): ... cls_name = self.__class__.__name__ ... return f'{cls_name}.{self.name}' ... >>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}" (OtherStyle.ALTERNATE, 'OtherStyle.ALTERNATE', 'OtherStyle.ALTERNATE')
- __str__(self)¶
回傳呼叫 str() 時使用的字串。預設回傳 Enum 名稱及成員名稱,但可以被覆寫:
>>> class OtherStyle(Enum): ... ALTERNATE = auto() ... OTHER = auto() ... SOMETHING_ELSE = auto() ... def __str__(self): ... return f'{self.name}' ... >>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}" (<OtherStyle.ALTERNATE: 1>, 'ALTERNATE', 'ALTERNATE')
- __format__(self)¶
回傳呼叫 format() 及 f-string 時使用的字串。預設回傳
__str__()
的回傳值,但可以被覆寫:>>> class OtherStyle(Enum): ... ALTERNATE = auto() ... OTHER = auto() ... SOMETHING_ELSE = auto() ... def __format__(self, spec): ... return f'{self.name}' ... >>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}" (<OtherStyle.ALTERNATE: 1>, 'OtherStyle.ALTERNATE', 'ALTERNATE')
在 3.12 版的變更: 新增 Dataclass support
- class enum.IntEnum¶
IntEnum 和 Enum 一樣,但其成員同時也是整數而可以被用在任何使用整數的地方。如果 IntEnum 成員經過任何整數運算,其結果會失去列舉狀態。
>>> from enum import IntEnum >>> class Number(IntEnum): ... ONE = 1 ... TWO = 2 ... THREE = 3 ... >>> Number.THREE <Number.THREE: 3> >>> Number.ONE + Number.TWO 3 >>> Number.THREE + 5 8 >>> Number.THREE == 3 True
在 3.11 版的變更: 為了更好地支援現存常數取代 (replacement of existing constants) 的使用情境,
__str__()
現在會是int.__str__()
。為了同樣的理由,__format__()
已經是int.__format__()
。
- class enum.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 版被加入.
- class enum.Flag¶
Flag
與Enum
相同,但其成員支援位元運算子&
(AND)、|
(OR)、^
(XOR) 和~
(INVERT);這些操作的結果是列舉的成員(的別名)。- __contains__(self, value)¶
如果 value 在 self 裡則回傳 True:
>>> from enum import Flag, auto >>> class Color(Flag): ... RED = auto() ... GREEN = auto() ... BLUE = auto() ... >>> purple = Color.RED | Color.BLUE >>> white = Color.RED | Color.GREEN | Color.BLUE >>> Color.GREEN in purple False >>> Color.GREEN in white True >>> purple in white True >>> white in purple False
- __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>
- class enum.IntFlag¶
IntFlag 和 Flag 一樣,但其成員同時也是整數而可以被用在任何使用整數的地方。
>>> from enum import IntFlag, auto >>> class Color(IntFlag): ... RED = auto() ... GREEN = auto() ... BLUE = auto() ... >>> Color.RED & 2 <Color: 0> >>> Color.RED | 2 <Color.RED|GREEN: 3>
如果 IntFlag 成員經過任何整數運算,其結果不是 IntFlag:
>>> Color.RED + 2 3
如果 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
的行為。
- class enum.ReprEnum¶
ReprEnum
使用Enum
的repr()
,但使用混合資料類型的str()
:繼承
ReprEnum
來保留混合資料類型的str()
/format()
,而不是使用Enum
預設的str()
。在 3.11 版被加入.
- class enum.EnumCheck¶
EnumCheck 包含
verify()
裝飾器使用的選項,以確保多樣的限制,不符合限制會產生ValueError
。- UNIQUE¶
確保每個值只有一個名稱:
>>> from enum import Enum, verify, UNIQUE >>> @verify(UNIQUE) ... class Color(Enum): ... RED = 1 ... GREEN = 2 ... BLUE = 3 ... CRIMSON = 1 Traceback (most recent call last): ... ValueError: aliases found in <enum 'Color'>: CRIMSON -> RED
- CONTINUOUS¶
確保在最小值成員跟最大值成員間沒有缺少值:
>>> from enum import Enum, verify, CONTINUOUS >>> @verify(CONTINUOUS) ... class Color(Enum): ... RED = 1 ... GREEN = 2 ... BLUE = 5 Traceback (most recent call last): ... ValueError: invalid enum 'Color': missing values 3, 4
- NAMED_FLAGS¶
確保任何旗標群組 / 遮罩只包含命名旗標 -- 當值是用指定而不是透過
auto()
產生時是很實用的:>>> from enum import Flag, verify, NAMED_FLAGS >>> @verify(NAMED_FLAGS) ... class Color(Flag): ... RED = 1 ... GREEN = 2 ... BLUE = 4 ... WHITE = 15 ... NEON = 31 Traceback (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 版被加入.
- class enum.FlagBoundary¶
FlagBoundary 控制在 Flag 及其子類別中如何處理範圍外的值。
- STRICT¶
範圍外的值會引發
ValueError
。這是Flag
的預設行為:>>> from enum import Flag, STRICT, auto >>> class StrictFlag(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 值:
>>> from enum import Flag, CONFORM, auto >>> class ConformFlag(Flag, boundary=CONFORM): ... RED = auto() ... GREEN = auto() ... BLUE = auto() ... >>> ConformFlag(2**2 + 2**4) <ConformFlag.BLUE: 4>
在 3.11 版被加入.
支援 __dunder__
名稱¶
__members__
是一個唯讀有序的成員名稱
:成員
項目的對映。只有在類別上可用。
如果指定了 __new__()
,它必須建立並回傳列舉成員;適當地設定成員的 _value_
也是一個很好的主意。一旦所有成員都建立之後就不會再被用到。
支援 _sunder_
名稱¶
_name_
-- 成員名稱_value_
-- 成員的值;可以在__new__
設定_missing_()
-- 當值沒有被找到時會使用的查詢函式;可以被覆寫_order_
-- 不再被使用,僅為了向後相容而保留(類別屬性,在類別建立時移除)_generate_next_value_()
-- 用來為列舉成員取得合適的值;可以被覆寫
在 3.6 版被加入: _missing_
、_order_
、_generate_next_value_
在 3.7 版被加入: _ignore_
通用項目與裝飾器¶
- class enum.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
並附上細節:>>> from enum import Enum, unique >>> @unique ... class Mistake(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
類型來建立自己的基礎類別:>>> from enum import Enum >>> class MyIntEnum(int, Enum): ... pass或者你也可以在你的列舉重新給定合適的
str()
:>>> from enum import Enum, IntEnum >>> class MyIntEnum(IntEnum): ... __str__ = Enum.__str__