Производные класса enum.Enum
включают в себя:
enum.IntEnum
.enum.StrEnum
.enum.IntFlag
.enum.Flag
.enum.Enum
.enum.IntEnum
.Первый предоставленный вариант Enum
является подклассом int
. Члены класса enum.IntEnum
можно сравнить с целыми числами. По сути, целочисленные перечисления разных типов также можно сравнивать друг с другом:
>>> from enum import IntEnum >>> class Shape(IntEnum): ... CIRCLE = 1 ... SQUARE = 2 ... >>> class Request(IntEnum): ... POST = 1 ... GET = 2 ... >>> Shape == 1 # False >>> Shape.CIRCLE == 1 # True >>> Shape.CIRCLE == Request.POST # True
Однако, их все равно нельзя сравнивать со стандартными перечислениями enum.Enum
:
>>> class Shape(IntEnum): ... CIRCLE = 1 ... SQUARE = 2 ... >>> class Color(Enum): ... RED = 1 ... GREEN = 2 ... >>> Shape.CIRCLE == Color.RED # False
Значения enum.IntEnum
ведут себя как целые числа и в других отношениях:
>>> int(Shape.CIRCLE) # 1 >>> ['a', 'b', 'c'][Shape.CIRCLE] # 'b' >>> [i for i in range(Shape.SQUARE)] # [0, 1]
enum.StrEnum
.Добавлен в Python 3.11.
Класс enum.StrEnum
является подклассом str
. Элементы enum.StrEnum
можно сравнивать со строками. По расширению, строковые перечисления разных типов также можно сравнивать друг с другом.
enum.IntFlag
.Добавлен в Python 3.6.
Следующий вариант Enum
, это enum.IntFlag
, основан на типе int
. Разница в том, что члены IntFlag
могут быть объединены с помощью побитовых операторов (&, |, ^, ~)
, и результатом по-прежнему остается член enum.IntFlag
, если это возможно. Как и enum.IntEnum
, члены enum.IntFlag
также являются целыми числами и могут использоваться везде, где используется целое число.
Примечание. Любая операция над элементом
enum.IntFlag
, кроме побитовых, потеряет членство вenum.IntFlag
.Побитовые операции, которые приводят к недопустимым значениям
enum.IntFlag
, теряют принадлежность кenum.IntFlag
. Подробнее в описанииenum.FlagBoundary
.
Изменено в Pytrhon 3.11.
Пример класса enum.IntFlag
:
>>> from enum import IntFlag >>> class Perm(IntFlag): ... R = 4 ... W = 2 ... X = 1 ... >>> Perm.R | Perm.W <Perm.R|W: 6> >>> Perm.R + Perm.W # 6 >>> RW = Perm.R | Perm.W >>> Perm.R in RW # True
Также можно именовать члены IntFlag
комбинациями из других членов этого класса:
>>> class Perm(IntFlag): ... R = 4 ... W = 2 ... X = 1 ... RWX = 7 >>> Perm.RWX # <Perm.RWX: 7> >>> ~Perm.RWX # <Perm: 0> >>> Perm(7) # <Perm.RWX: 7>
Примечание. Именованные комбинации считаются псевдонимами. Псевдонимы не отображаются во время итерации, но могут быть возвращены при поиске по значению. Изменено в Pytrhon 3.11.
Еще одно важное различие между enum.IntFlag
и enum.Enum
заключается в том, что если флаги не установлены (значение 0), то его логическая оценка будет False
:
>>> Perm.R & Perm.X # <Perm: 0> >>> bool(Perm.R & Perm.X) # False
Поскольку члены enum.IntFlag
также являются подклассами int
, то они могут быть объединены с ними (но могут потерять членство в enum.IntFlag
):
>>> Perm.X | 4 # <Perm.R|X: 5> >>> Perm.X | 8 # 9
Примечание. Оператор отрицания
~
всегда возвращает элементenum.IntFlag
с положительным значением:>>> (~Perm.X).value == (Perm.R|Perm.W).value == 6 #True
Члены enum.IntFlag
также могут быть повторены (Новое в Python 3.11):
list(RW) [<Perm.R: 4>, <Perm.W: 2>]
enum.Flag
.Новое в Python 3.6.
Последняя вариация - это enum.Flag
. Как и enum.IntFlag
, члены enum.Flag
можно комбинировать с помощью побитовых операторов (&, |, ^, ~)
.
В отличие от enum.IntFlag
, они не могут быть объединены или сравнены с любым другим перечислением enum.Flag
или типом int
. Хотя можно указать значения напрямую, рекомендуется использовать класс enum.auto
в качестве значения и позволить классу Flag
выбрать соответствующее значение.
Как и в случае с IntFlag
, если комбинация членов Flag
не приводит к установке флагов, логическая оценка имеет значение False
:
>>> from enum import Flag, auto >>> class Color(Flag): ... RED = auto() ... BLUE = auto() ... GREEN = auto() ... >>> Color.RED & Color.GREEN # <Color: 0> >>> bool(Color.RED & Color.GREEN) # False
Отдельные флаги должны иметь значения, являющиеся степенями двойки (1, 2, 4, 8,…)
, в то время как комбинации флагов не будут:
>>> class Color(Flag): ... RED = auto() ... BLUE = auto() ... GREEN = auto() ... WHITE = RED | BLUE | GREEN ... >>> Color.WHITE # <Color.WHITE: 7>
Присвоение имени условию "no flags set" не изменяет его логическое значение:
>>> class Color(Flag): ... BLACK = 0 ... RED = auto() ... BLUE = auto() ... GREEN = auto() ... >>> Color.BLACK # <Color.BLACK: 0> >>> bool(Color.BLACK) # False
Члены enum.Flag
также могут быть повторены (Новое в Python 3.11):
>>> purple = Color.RED | Color.BLUE >>> list(purple) # [<Color.RED: 1>, <Color.BLUE: 2>]
Примечание. Для большинства нового кода настоятельно рекомендуются использовать классы
enum.Enum
иenum.Flag
, посколькуenum.IntEnum
иenum.IntFlag
нарушают некоторые семантические ожидания от перечисления (будучи сопоставимыми с целыми числами и, следовательно, транзитивностью к другим несвязанным перечислениям).enum.IntEnum
иenum.IntFlag
следует использовать только в тех случаях, когдаEnum
иFlag
не подходят. Например, когда целочисленные константы заменяются перечислениями или для взаимодействия с другими системами.
enum.Enum
.Хотя класс enum.IntEnum
является частью модуля enum
, его было бы очень просто реализовать независимо:
class IntEnum(int, Enum): pass
Это демонстрирует, как могут быть определены аналогичные производные перечисления. Например FloatEnum
, который смешивается с типом float
вместо int
.
Некоторые правила:
Enum
смешанные типы должны появляться перед самим Enum
в последовательности оснований, как в примере с IntEnum
выше.bool
и range
не являются подклассами и вызовут ошибку во время создания Enum
, если они используются в качестве типа микширования.Enum
может иметь члены любого типа, однако после добавления дополнительного типа все члены должны иметь значения этого типа, например int
. Это ограничение не применяется к миксам, которые только добавляют методы и не указывают другой тип.value
не совпадает с самим членом перечисления, хотя он эквивалентен и будет в сравнениях равным.%
: %s
и %r
вызывают __str__()
и __repr__()
класса Enum
соответственно. Другие коды (например, %i
или %h
для IntEnum
) рассматривают член перечисления как его смешанный тип.str.format()
и format()
будут использовать метод перечисления __str__()
.Примечание. Поскольку
IntEnum
,IntFlag
иStrEnum
предназначены для замены существующих констант, их метод__str__()
был сброшен на метод их типов данных__str__()
.