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', 'GREEN', 'BLUE'])

雖然我們可以用 class 語法來建立列舉,列舉並不是標準的 Python 類別。參考列舉有何差異以取得更多細節。

備註

命名方式

  • Color 類別是一個列舉(或 enum

  • Color.REDColor.GREEN 等屬性是列舉成員(或成員),並且使用上可以看作常數。

  • 列舉成員有名稱Color.RED 的名稱是 REDColor.BLUE 的值是 3 諸如此類)


模組內容

EnumType

Enum 及其子類別的 type

Enum

用來建立列舉常數的基礎類別。

IntEnum

用來建立列舉常數的基礎類別,同時也是 int 的子類別。(備註

StrEnum

用來建立列舉常數的基礎類別,同時也是 str 的子類別。(備註

Flag

用來建立列舉常數的基礎類別,可以使用位元操作來結合成員且其結果不失去 Flag 的成員資格。

IntFlag

用來建立列舉常數的基礎類別,可以使用位元操作來結合成員且其結果不失去 IntFlag 的成員資格。IntFlag 的成員也是 int 的子類別。(備註

ReprEnum

IntEnumStrEnumIntFlag 所使用來保留這些混合類型的 str()

EnumCheck

一個有 CONTINUOUSNAMED_FLAGSUNIQUE 這些值的列舉,和 verify() 一起使用來確保給定的列舉符合多種限制。

FlagBoundary

一個有 STRICTCONFORMEJECTKEEP 這些值的列舉,允許列舉對如何處理非法值做更細微的控制。

auto

列舉成員的實例會被取代成合適的值。StrEnum 預設是小寫版本的成員名稱,其它列舉則預設是 1 且往後遞增。

property()

允許 Enum 成員擁有屬性且不會與成員名稱有衝突。valuename 屬性是用這個方式來實作。

unique()

Enum 類別的裝飾器,用來確保任何值只有綁定到一個名稱上。

verify()

Enum 類別的裝飾器,用來檢查列舉上使用者所選的限制。

member()

obj 變成成員。可以當作裝飾器使用。

nonmember()

不讓 obj 變成成員。可以當作裝飾器使用。

global_enum()

修改列舉上的 str()repr() ,讓成員顯示為屬於模組而不是類別,並將該列舉成員匯出到全域命名空間。

show_flag_values()

回傳旗標 (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列舉metaclassEnumType 可以有子類別 -- 細節請參考 建立 EnumType 的子類別

EnumType is responsible for setting the correct __repr__(), __str__(), __format__(), and __reduce__() methods on the final enum, as well as creating the enum members, properly handling duplicates, providing iteration over the enum class, etc.

__call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

這個方法可以用兩種不同的方式呼叫:

  • 查詢已存在的成員:

    cls:

    所呼叫的列舉類別。

    value:

    要查詢的值。

  • 使用 cls 列舉來建立新列舉(只有在現有列舉沒有任何成員時)

    cls:

    所呼叫的列舉類別。

    value:

    要建立的新列舉的名稱。

    names:

    新列舉的成員的名稱/值。

    module:

    新列舉要建立在哪個模組名稱下。

    qualname:

    這個列舉在模組裡實際上的位置。

    type:

    新列舉的混合類型。

    start:

    列舉的第一個整數值(由 auto 所使用)

    boundary:

    在位元操作時怎麼處理範圍外的值(只有 Flag 會用到)

__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__']
__getitem__(cls, name)

回傳 cls 中符合 name 的列舉成員,或引發 KeyError

>>> Color['BLUE']
<Color.BLUE: 3>
__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_alias_()

Adds a new name as an alias to an existing member. Raises a NameError if the name is already assigned to a different member.

_add_value_alias_()

Adds a new value as an alias to an existing member. Raises a ValueError if the value is already linked with a different member.

在 3.11 版被加入: Before 3.11 EnumType was called EnumMeta, which is still available as an alias.

class enum.Enum

Enum 是所有 enum 列舉的基礎類別。

name

用來定義 Enum 成員的名稱:

>>> Color.BLUE.name
'BLUE'
value

Enum 成員給定的值:

>>> Color.RED.value
1

成員的值,可以在 __new__() 設定。

備註

列舉成員的值

成員的值可以是任何值:intstr 等等。如果實際使用什麼值並不重要,你可以使用 auto 實例,它會為你選擇合適的值。更多細節請參考 auto

While mutable/unhashable values, such as dict, list or a mutable dataclass, 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_

成員名稱。

_value_

成員的值,可以在 __new__() 設定。

_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 of 26 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')

備註

Enum 使用 auto 會產生從 1 開始遞增的整數。

在 3.12 版的變更: 新增 Dataclass support

class enum.IntEnum

IntEnum is the same as Enum, but its members are also integers and can be used anywhere that an integer can be used. If any integer operation is performed with an IntEnum member, the resulting value loses its enumeration status.

>>> 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

備註

IntEnum 使用 auto 會產生從 1 開始遞增的整數。

在 3.11 版的變更: 為了更好地支援現存常數取代 (replacement of existing constants) 的使用情境,__str__() 現在會是 int.__str__()。為了同樣的理由,__format__() 已經是 int.__format__()

class enum.StrEnum

StrEnum is the same as Enum, but its members are also strings and can be used in most of the same places that a string can be used. The result of any string operation performed on or with a StrEnum member is not part of the enumeration.

備註

stdlib 裡有些地方會檢查只能是 str 而不是 str 的子類別(也就是 type(unknown) == str 而不是 isinstance(unknown, str)),在這些地方你需要使用 str(StrEnum.member)

備註

StrEnum 使用 auto 會產生小寫的成員名稱當作值。

備註

為了更好地支援現存常數取代 (replacement of existing constants) 的使用情境,__str__() 現在會是 str.__str__()。為了同樣的理由,__format__() 也會是 str.__format__()

在 3.11 版被加入.

class enum.Flag

FlagEnum 相同,但其成員支援位元運算子 & (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):

Returns all the flags in type(self) that are not in self:

>>> ~white
<Color: 0>
>>> ~purple
<Color.GREEN: 2>
>>> ~Color.RED
<Color.GREEN|BLUE: 6>
_numeric_repr_()

用來格式化任何剩下未命名數值的函式。預設是值的 repr,常見選擇是 hex()oct()

備註

Flag 使用 auto 會產生從 1 開始 2 的次方的整數。

在 3.11 版的變更: 值為 0 的旗標的 repr() 已改變。現在是:

>>> Color(0) 
<Color: 0>
class enum.IntFlag

IntFlag is the same as Flag, but its members are also integers and can be used anywhere that an integer can be used.

>>> 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

If a Flag operation is performed with an IntFlag member and:

  • 結果是合法的 IntFlag:回傳 IntFlag

  • the result is not a valid IntFlag: the result depends on the FlagBoundary setting

The repr() of unnamed zero-valued flags has changed. It is now:

>>> Color(0)
<Color: 0>

備註

IntFlag 使用 auto 會產生從 1 開始 2 的次方的整數。

在 3.11 版的變更: 為了更好地支援現存常數取代 (replacement of existing constants) 的使用情境,__str__() 現在會是 int.__str__()。為了同樣的理由,__format__() 已經是 int.__format__()

IntFlag 的反轉 (inversion) 現在會回傳正值,該值是不在給定旗標的所有旗標聯集,而不是一個負值。這符合現有 Flag 的行為。

class enum.ReprEnum

ReprEnum 使用 Enumrepr(),但使用混合資料類型的 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 controls how out-of-range values are handled in Flag and its subclasses.

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

Out-of-range values have invalid values removed, leaving a valid Flag value:

>>> 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

Out-of-range values lose their Flag membership and revert to 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

Out-of-range values are kept, and the Flag membership is kept. This is the default for 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 版被加入.


支援 __dunder__ 名稱

__members__ 是一個唯讀有序的成員名稱成員項目的對映。只有在類別上可用。

__new__(), if specified, must create and return the enum members; it is also a very good idea to set the member's _value_ appropriately. Once all the members are created it is no longer used.

支援 _sunder_ 名稱

  • _add_alias_() -- adds a new name as an alias to an existing member.

  • _add_value_alias_() -- adds a new value as an alias to an existing member.

  • _name_ -- 成員名稱

  • _value_ -- 成員的值;可以在 __new__ 設定

  • _missing_() -- 當值沒有被找到時會使用的查詢函式;可以被覆寫

  • _ignore_ -- 一個名稱的串列,可以是 liststr,它不會被轉換成成員,且在最後的類別上會被移除

  • _order_ -- 不再被使用,僅為了向後相容而保留(類別屬性,在類別建立時移除)

  • _generate_next_value_() -- 用來為列舉成員取得合適的值;可以被覆寫

    備註

    For standard Enum classes the next value chosen is the highest value seen incremented by one.

    For Flag classes the next value chosen will be the next highest power-of-two.

  • While _sunder_ names are generally reserved for the further development of the Enum class and can not be used, some are explicitly allowed:

在 3.6 版被加入: _missing__order__generate_next_value_

在 3.7 版被加入: _ignore_

在 3.13 版被加入: _add_alias_, _add_value_alias_, _repr_*


通用項目與裝飾器

class enum.auto

auto can be used in place of a value. If used, the Enum machinery will call an Enum's _generate_next_value_() to get an appropriate value. For Enum and IntEnum that appropriate value will be the last value plus one; for Flag and IntFlag it will be the first power-of-two greater than the highest value; for StrEnum it will be the lower-cased version of the member's name. Care must be taken if mixing auto() with manually specified values.

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 相似的裝飾器,但只專門針對列舉。它允許成員屬性和成員本身有相同名稱。

備註

屬性和成員必須定義在分開的類別裡;例如 valuename 屬性定義在 Enum 類別而 Enum 子類別可以定義成員名稱為 valuename

在 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.verify

專門針對列舉的 class 裝飾器。使用 EnumCheck 裡的成員來指定在裝飾的列舉上應該檢查什麼限制。

在 3.11 版被加入.

@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 版被加入.


備註

IntEnumStrEnumIntFlag

這三種列舉類型是設計來直接取代現有以整數及字串為基底的值;因此它們有額外的限制:

  • __str__ 使用值而不是列舉成員的名稱

  • __format__ 因為使用 __str__,也會使用值而不是列舉成員的名稱

如果你不需要或不想要這些限制,你可以透過混合 intstr 類型來建立自己的基礎類別:

>>> from enum import Enum
>>> class MyIntEnum(int, Enum):
...     pass

或者你也可以在你的列舉重新給定合適的 str()

>>> from enum import Enum, IntEnum
>>> class MyIntEnum(IntEnum):
...     __str__ = Enum.__str__