enum
--- 對列舉的支援¶
在 3.4 版被加入.
原始碼:Lib/enum.py
列舉:
是一組綁定唯一值的代表名稱(成員)
可以用疊代的方式以定義的順序回傳其正式 (canonical)(即非別名)成員
使用 call 語法來透過值回傳成員
使用 index 語法來透過名稱回傳成員
列舉透過 class
語法或函式呼叫的語法來建立:
>>> from enum import Enum
>>> # class 語法
>>> class Color(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
資料型別¶
- class enum.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_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>]
- _add_value_alias_()¶
新增一個值作為現有成員的別名。如果該值已與不同成員連結,則會引發
ValueError
。
在 3.11 版被加入: 在 3.11 之前,
EnumType
稱作EnumMeta
,其目前仍可作為別名使用。
- class enum.Enum¶
Enum 是所有 enum 列舉的基礎類別。
- name¶
用來定義
Enum
成員的名稱:>>> Color.BLUE.name 'BLUE'
- _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
會產生呼叫
int('1a', 16)
而該成員的值為26
。備註
當寫自訂的
__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>
- EJECT¶
範圍外的值會失去它們的
Flag
成員資格且恢復成int
。>>> from enum import Flag, EJECT, auto >>> class EjectFlag(Flag, boundary=EJECT): ... RED = auto() ... GREEN = auto() ... BLUE = auto() ... >>> EjectFlag(2**2 + 2**4) 20
- KEEP¶
範圍外的值會被保留,
Flag
成員資格也會被保留。這是IntFlag
的預設行為:>>> from enum import Flag, KEEP, auto >>> class KeepFlag(Flag, boundary=KEEP): ... RED = auto() ... GREEN = auto() ... BLUE = auto() ... >>> KeepFlag(2**2 + 2**4) <KeepFlag.BLUE|16: 20>
在 3.11 版被加入.
- class enum.EnumDict¶
EnumDict is a subclass of
dict
that is used as the namespace for defining enum classes (see Preparing the class namespace). It is exposed to allow subclasses ofEnumType
with advanced behavior like having multiple values per member. It should be called with the name of the enum class being created, otherwise private names and internal classes will not be handled correctly.Note that only the
MutableMapping
interface (__setitem__()
andupdate()
) is overridden. It may be possible to bypass the checks using otherdict
operations like|=
.- member_names¶
A list of 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_*
通用項目與裝飾器¶
- 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__