enum.md
1> **Источник:** https://python-all.ru/3.4/library/enum.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 8.13. [`enum`](https://python-all.ru/3.4/library/enum.html#module-enum) – Поддержка перечислений89Новое в версии 3.4.1011**Исходный код:** [Lib/enum.py](https://python-all.ru/src/3.4/Lib/enum.py)1213---1415Перечисление – это набор символических имён (членов), привязанных к уникальным постоянным значениям. Внутри перечисления члены можно сравнивать по идентичности, а само перечисление можно перебирать.1617## 8.13.1. Содержание модуля1819Этот модуль определяет два класса перечислений, которые можно использовать для определения уникальных наборов имён и значений: [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) и [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum). Он также определяет один декоратор, [`unique()`](https://python-all.ru/3.4/library/enum.html#enum.unique).2021#### `class enum.Enum`2223Базовый класс для создания перечислимых констант. См. раздел [Функциональный API](https://python-all.ru/3.4/library/enum.html#functional-api) для альтернативного синтаксиса создания.2425#### `class enum.IntEnum`2627Базовый класс для создания перечисляемых констант, которые также являются подклассами [`int`](https://python-all.ru/3.4/library/functions.html#int).2829#### `enum.unique()`3031Декоратор класса перечисления, который гарантирует, что каждому значению соответствует только одно имя.3233## 8.13.2. Создание Enum3435Перечисления создаются с помощью синтаксиса [`class`](https://python-all.ru/3.4/reference/compound_stmts.html#class), что делает их лёгкими для чтения и написания. Альтернативный метод создания описан в [Функциональном API](https://python-all.ru/3.4/library/enum.html#functional-api). Чтобы определить перечисление, создайте подкласс [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) следующим образом:3637```python38>>> from enum import Enum39>>> class Color(Enum):40... red = 141... green = 242... blue = 343...44```4546> **Примечание**47>48> Терминология49>50> - Класс `Color` является *перечислением* (или *enum*)51> - Атрибуты `Color.red`, `Color.green` и т.д. являются *членами перечисления* (или *членами enum*).52> - Члены enum имеют *имена* и *значения* (имя `Color.red` – `red`, значение `Color.blue` – `3` и т.д.)5354> **Примечание**55>56> Хотя мы используем синтаксис [`class`](https://python-all.ru/3.4/reference/compound_stmts.html#class) для создания перечислений, перечисления не являются обычными классами Python. Смотрите [Чем перечисления отличаются?](https://python-all.ru/3.4/library/enum.html#how-are-enums-different) для получения дополнительных сведений.5758Члены перечисления имеют удобочитаемые строковые представления:5960```python61>>> print(Color.red)62Color.red63```6465...в то время как их `repr` содержит больше информации:6667```python68>>> print(repr(Color.red))69<Color.red: 1>70```7172*Тип* члена перечисления – это перечисление, к которому он принадлежит:7374```python75>>> type(Color.red)76<enum 'Color'>77>>> isinstance(Color.green, Color)78True79>>>80```8182Члены перечисления также имеют свойство, содержащее только их имя:8384```python85>>> print(Color.red.name)86red87```8889Перечисления поддерживают итерацию в порядке определения:9091```python92>>> class Shake(Enum):93... vanilla = 794... chocolate = 495... cookies = 996... mint = 397...98>>> for shake in Shake:99... print(shake)100...101Shake.vanilla102Shake.chocolate103Shake.cookies104Shake.mint105```106107Члены перечисления хешируемы, поэтому их можно использовать в словарях и множествах:108109```python110>>> apples = {}111>>> apples[Color.red] = 'red delicious'112>>> apples[Color.green] = 'granny smith'113>>> apples == {Color.red: 'red delicious', Color.green: 'granny smith'}114True115```116117## 8.13.3. Программный доступ к членам перечисления и их атрибутам118119Иногда полезно получать доступ к членам перечислений программно (т.е. в ситуациях, когда `Color.red` не подходит, потому что точный цвет неизвестен во время написания программы). `Enum` предоставляет такой доступ:120121```python122>>> Color(1)123<Color.red: 1>124>>> Color(3)125<Color.blue: 3>126```127128Если требуется обратиться к членам перечисления по *имени*, используйте доступ по ключу:129130```python131>>> Color['red']132<Color.red: 1>133>>> Color['green']134<Color.green: 2>135```136137Если у вас есть член перечисления и вам нужно его `имя` или `значение`:138139```python140>>> member = Color.red141>>> member.name142'red'143>>> member.value1441145```146147## 8.13.4. Дублирование членов enum и значений148149Наличие двух членов перечисления с одинаковым именем недопустимо:150151```python152>>> class Shape(Enum):153... square = 2154... square = 3155...156Traceback (most recent call last):157...158TypeError: Attempted to reuse key: 'square'159```160161Однако двум членам перечисления разрешено иметь одинаковое значение. Если два члена A и B имеют одинаковое значение (и A определён первым), то B является псевдонимом A. Поиск по значению A и B вернёт A. Поиск по имени B также вернёт A:162163```python164>>> class Shape(Enum):165... square = 2166... diamond = 1167... circle = 3168... alias_for_square = 2169...170>>> Shape.square171<Shape.square: 2>172>>> Shape.alias_for_square173<Shape.square: 2>174>>> Shape(2)175<Shape.square: 2>176```177178> **Примечание**179>180> Попытка создать член с тем же именем, что и уже определённый атрибут (другой член, метод и т.д.), или попытка создать атрибут с тем же именем, что и член, не допускается.181182## 8.13.5. Обеспечение уникальности значений перечисления183184По умолчанию перечисления допускают несколько имён в качестве псевдонимов для одного и того же значения. Если такое поведение нежелательно, можно использовать следующий декоратор, чтобы гарантировать, что каждое значение используется в перечислении только один раз:185186#### `@enum.unique`187188Декоратор [`class`](https://python-all.ru/3.4/reference/compound_stmts.html#class) специально для перечислений. Он ищет в `__members__` перечисления любые найденные псевдонимы; если они найдены, возбуждается [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError) с подробностями:189190```python191>>> from enum import Enum, unique192>>> @unique193... class Mistake(Enum):194... one = 1195... two = 2196... three = 3197... four = 3198...199Traceback (most recent call last):200...201ValueError: duplicate values found in <enum 'Mistake'>: four -> three202```203204## 8.13.6. Итерация205206Перебор членов перечисления не включает псевдонимы:207208```python209>>> list(Shape)210[<Shape.square: 2>, <Shape.diamond: 1>, <Shape.circle: 3>]211```212213Специальный атрибут `__members__` является упорядоченным словарём, отображающим имена в члены. Он включает все имена, определённые в перечислении, включая псевдонимы:214215```python216>>> for name, member in Shape.__members__.items():217... name, member218...219('square', <Shape.square: 2>)220('diamond', <Shape.diamond: 1>)221('circle', <Shape.circle: 3>)222('alias_for_square', <Shape.square: 2>)223```224225Атрибут `__members__` можно использовать для детального программного доступа к членам перечисления. Например, для поиска всех псевдонимов:226227```python228>>> [name for name, member in Shape.__members__.items() if member.name != name]229['alias_for_square']230```231232## 8.13.7. Сравнения233234Члены перечисления сравниваются по идентичности:235236```python237>>> Color.red is Color.red238True239>>> Color.red is Color.blue240False241>>> Color.red is not Color.blue242True243```244245Упорядоченные сравнения между значениями перечисления *не* поддерживаются. Члены перечисления – не целые числа (но см. [IntEnum](https://python-all.ru/3.4/library/enum.html#intenum) ниже):246247```python248>>> Color.red < Color.blue249Traceback (most recent call last):250 File "<stdin>", line 1, in <module>251TypeError: unorderable types: Color() < Color()252```253254Однако сравнения на равенство определены:255256```python257>>> Color.blue == Color.red258False259>>> Color.blue != Color.red260True261>>> Color.blue == Color.blue262True263```264265Сравнения со значениями, не являющимися перечислениями, всегда будут давать результат «не равно» (опять же, [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum) был явно спроектирован для другого поведения, см. ниже):266267```python268>>> Color.blue == 2269False270```271272## 8.13.8. Допустимые члены и атрибуты перечислений273274В примерах выше для значений перечислений используются целые числа. Использование целых чисел – это кратко и удобно (и предусмотрено по умолчанию [функциональным API](https://python-all.ru/3.4/library/enum.html#functional-api)), но не является строгим требованием. В подавляющем большинстве случаев не важно, каково фактическое значение элемента перечисления. Но если значение *является* важным, перечисления могут иметь произвольные значения.275276Перечисления – это классы Python и могут иметь обычные методы и специальные методы. Если есть такое перечисление:277278```python279>>> class Mood(Enum):280... funky = 1281... happy = 3282...283... def describe(self):284... # self – это член перечисления285... return self.name, self.value286...287... def __str__(self):288... return 'my custom str! {0}'.format(self.value)289...290... @classmethod291... def favorite_mood(cls):292... # cls здесь – это перечисление293... return cls.happy294...295```296297Тогда:298299```python300>>> Mood.favorite_mood()301<Mood.happy: 3>302>>> Mood.happy.describe()303('happy', 3)304>>> str(Mood.funky)305'my custom str! 1'306```307308Правила для того, что разрешено, таковы: имена \_sunder\_ (начинающиеся и заканчивающиеся одним подчёркиванием) зарезервированы перечислением и не могут использоваться; все остальные атрибуты, определённые в перечислении, станут членами этого перечисления, за исключением имён *\_\_dunder\_\_* и дескрипторов (методы также являются дескрипторами).309310Примечание: если ваше перечисление определяет [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) и/или [`__init__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__init__), то любые значения, переданные члену перечисления, будут переданы этим методам. Смотрите [Planet](https://python-all.ru/3.4/library/enum.html#planet) для примера.311312## 8.13.9. Ограниченное наследование перечислений313314Создание подкласса перечисления разрешено только в том случае, если перечисление не определяет никаких членов. Так делать запрещено:315316```python317>>> class MoreColor(Color):318... pink = 17319...320Traceback (most recent call last):321...322TypeError: Cannot extend enumerations323```324325Но это разрешено:326327```python328>>> class Foo(Enum):329... def some_behavior(self):330... pass331...332>>> class Bar(Foo):333... happy = 1334... sad = 2335...336```337338Разрешение создания подклассов перечислений, определяющих члены, привело бы к нарушению некоторых важных инвариантов типов и экземпляров. С другой стороны, имеет смысл разрешить общее поведение для группы перечислений. (Пример см. в [OrderedEnum](https://python-all.ru/3.4/library/enum.html#orderedenum).)339340## 8.13.10. Сериализация341342Перечисления могут быть упакованы и распакованы с помощью модуля pickle.343344```python345>>> from test.test_enum import Fruit346>>> from pickle import dumps, loads347>>> Fruit.tomato is loads(dumps(Fruit.tomato))348True349```350351Обычные ограничения для упаковки с помощью модуля pickle применяются: перечисления, которые можно упаковать, должны быть определены на верхнем уровне модуля, так как для распаковки их нужно импортировать из этого модуля.352353> **Примечание**354>355> С протоколом pickle версии 4 можно легко упаковывать перечисления, вложенные в другие классы.356357Можно изменить способ сериализации/десериализации членов Enum, определив [`__reduce_ex__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce_ex__) в классе перечисления.358359## 8.13.11. Функциональный API360361Класс [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) является вызываемым, предоставляя следующий функциональный API:362363```python364>>> Animal = Enum('Animal', 'ant bee cat dog')365>>> Animal366<enum 'Animal'>367>>> Animal.ant368<Animal.ant: 1>369>>> Animal.ant.value3701371>>> list(Animal)372[<Animal.ant: 1>, <Animal.bee: 2>, <Animal.cat: 3>, <Animal.dog: 4>]373```374375Семантика этого API напоминает [`namedtuple`](https://python-all.ru/3.4/library/collections.html#collections.namedtuple). Первый аргумент вызова [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) – это имя перечисления.376377Второй аргумент – это *источник* имён членов перечисления. Он может быть строкой имён, разделённых пробелами, последовательностью имён, последовательностью 2-кортежей с парами ключ/значение или отображением (например, словарём) имён в значения. Последние два варианта позволяют присваивать перечислениям произвольные значения; остальные автоматически присваивают возрастающие целые числа, начиная с 1. Возвращается новый класс, производный от [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum). Другими словами, приведённое выше присваивание `Animal` эквивалентно:378379```python380>>> class Animal(Enum):381... ant = 1382... bee = 2383... cat = 3384... dog = 4385...386```387388Причина выбора `1` в качестве начального числа, а не `0`, заключается в том, что `0` является `False` в логическом смысле, но все члены enum вычисляются в `True`.389390Сериализация перечислений, созданных с помощью функционального API, может быть сложной, поскольку для определения модуля, в котором создаётся перечисление, используются детали реализации стека вызовов (например, это не сработает, если использовать вспомогательную функцию в отдельном модуле, а также может не работать в IronPython или Jython). Решение – явно указать имя модуля следующим образом:391392```python393>>> Animal = Enum('Animal', 'ant bee cat dog', module=__name__)394```395396> **Предупреждение**397>398> Если `module` не указан и Enum не может определить его, новые члены Enum не смогут быть десериализованы; чтобы ошибки оставались ближе к источнику, сериализация будет отключена.399400Новый протокол pickle 4 также в некоторых обстоятельствах полагается на установку `__qualname__` в место, где pickle сможет найти класс. Например, если класс был сделан доступным в классе SomeData в глобальной области видимости:401402```python403>>> Animal = Enum('Animal', 'ant bee cat dog', qualname='SomeData.Animal')404```405406Полная сигнатура:407408```python409Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>)410```411412| значение: | Что новый класс Enum запишет в качестве своего имени. |413| --- | --- |414| имена: | Члены Enum. Это может быть строка, разделённая пробелами или запятыми (значения будут начинаться с 1): 'red green blue' \| 'red,green,blue' \| 'red, green, blue' или итератор имён: \['red', 'green', 'blue'\] или итератор пар (имя, значение): \[('cyan', 4), ('magenta', 5), ('yellow', 6)\] или отображение: {'chartreuse': 7, 'sea\_green': 11, 'rosemary': 42} |415| модуль: | имя модуля, в котором находится новый класс Enum. |416| qualname: | где в модуле находится новый класс Enum. |417| тип: | тип, который следует примешать к новому классу Enum. |418419## 8.13.12. Производные перечисления420421### 8.13.12.1. IntEnum422423Предоставляется разновидность [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum), которая также является подклассом [`int`](https://python-all.ru/3.4/library/functions.html#int). Члены [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum) можно сравнивать с целыми числами; кроме того, целочисленные перечисления разных типов также можно сравнивать друг с другом:424425```python426>>> from enum import IntEnum427>>> class Shape(IntEnum):428... circle = 1429... square = 2430...431>>> class Request(IntEnum):432... post = 1433... get = 2434...435>>> Shape == 1436False437>>> Shape.circle == 1438True439>>> Shape.circle == Request.post440True441```442443Однако их всё ещё нельзя сравнивать со стандартными перечислениями [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum):444445```python446>>> class Shape(IntEnum):447... circle = 1448... square = 2449...450>>> class Color(Enum):451... red = 1452... green = 2453...454>>> Shape.circle == Color.red455False456```457458Значения [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum) ведут себя как целые числа и в других ожидаемых аспектах:459460```python461>>> int(Shape.circle)4621463>>> ['a', 'b', 'c'][Shape.circle]464'b'465>>> [i for i in range(Shape.square)]466[0, 1]467```468469Для подавляющего большинства кода настоятельно рекомендуется [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum), поскольку [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum) нарушает некоторые семантические обещания перечисления (из-за возможности сравнения с целыми числами, а следовательно, по транзитивности и с другими не связанными перечислениями). Его следует использовать только в особых случаях, когда нет другого выбора; например, когда целочисленные константы заменяются перечислениями и требуется обратная совместимость с кодом, который всё ещё ожидает целые числа.470471### 8.13.12.2. Другие472473Хотя [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum) является частью модуля [`enum`](https://python-all.ru/3.4/library/enum.html#module-enum), его очень просто реализовать самостоятельно:474475```python476class IntEnum(int, Enum):477 pass478```479480Это демонстрирует, как можно определить подобные производные перечисления; например, `StrEnum`, в которое примешивается [`str`](https://python-all.ru/3.4/library/stdtypes.html#str) вместо [`int`](https://python-all.ru/3.4/library/functions.html#int).481482Некоторые правила:4834841. При наследовании от [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) типы-примеси должны располагаться перед самим [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) в последовательности базовых классов, как в примере с [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum) выше.4852. Хотя [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) может иметь члены любого типа, как только вы примешиваете дополнительный тип, все члены должны иметь значения этого типа, например, [`int`](https://python-all.ru/3.4/library/functions.html#int) выше. Это ограничение не распространяется на примеси, которые только добавляют методы и не задают другой тип данных, такой как [`int`](https://python-all.ru/3.4/library/functions.html#int) или [`str`](https://python-all.ru/3.4/library/stdtypes.html#str).4863. Когда примешивается другой тип данных, атрибут `value` *не совпадает* с самим членом перечисления, хотя он эквивалентен и будет сравниваться как равный.4874. Форматирование в стиле %: *%s* и *%r* вызывают [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum)'s [`__str__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__str__) и [`__repr__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__repr__) соответственно; другие коды (например, *%i* или *%h* для IntEnum) обрабатывают член перечисления как его примешанный тип.4885. `str.__format__()` (или [`format()`](https://python-all.ru/3.4/library/functions.html#format)) будет использовать метод [`__format__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__format__) примешанного типа. Если требуется получить [`str()`](https://python-all.ru/3.4/library/stdtypes.html#str) или [`repr()`](https://python-all.ru/3.4/library/functions.html#repr) класса [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum), используйте коды форматирования *!s* или *!r* [`str`](https://python-all.ru/3.4/library/stdtypes.html#str).489490## 8.13.13. Интересные примеры491492Хотя ожидается, что [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) и [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum) покрывают большинство вариантов использования, они не могут покрыть их все. Ниже приведены рецепты для некоторых различных типов перечислений, которые можно использовать напрямую или как примеры для создания собственных.493494### 8.13.13.1. AutoNumber495496Позволяет избежать необходимости указывать значение для каждого члена перечисления:497498```python499>>> class AutoNumber(Enum):500... def __new__(cls):501... value = len(cls.__members__) + 1502... obj = object.__new__(cls)503... obj._value_ = value504... return obj505...506>>> class Color(AutoNumber):507... red = ()508... green = ()509... blue = ()510...511>>> Color.green.value == 2512True513```514515> **Примечание**516>517> Метод [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__), если он определён, используется при создании членов Enum; затем он заменяется методом [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) класса Enum, который используется после создания класса для поиска существующих членов.518519### 8.13.13.2. OrderedEnum520521Упорядоченное перечисление, которое не основано на [`IntEnum`](https://python-all.ru/3.4/library/enum.html#enum.IntEnum) и поэтому сохраняет обычные инварианты [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) (например, невозможность сравнения с другими перечислениями):522523```python524>>> class OrderedEnum(Enum):525... def __ge__(self, other):526... if self.__class__ is other.__class__:527... return self.value >= other.value528... return NotImplemented529... def __gt__(self, other):530... if self.__class__ is other.__class__:531... return self.value > other.value532... return NotImplemented533... def __le__(self, other):534... if self.__class__ is other.__class__:535... return self.value <= other.value536... return NotImplemented537... def __lt__(self, other):538... if self.__class__ is other.__class__:539... return self.value < other.value540... return NotImplemented541...542>>> class Grade(OrderedEnum):543... A = 5544... B = 4545... C = 3546... D = 2547... F = 1548...549>>> Grade.C < Grade.A550True551```552553### 8.13.13.3. DuplicateFreeEnum554555Вызывает ошибку, если обнаружено дублирующееся имя члена, вместо создания псевдонима:556557```python558>>> class DuplicateFreeEnum(Enum):559... def __init__(self, *args):560... cls = self.__class__561... if any(self.value == e.value for e in cls):562... a = self.name563... e = cls(self.value).name564... raise ValueError(565... "aliases not allowed in DuplicateFreeEnum: %r --> %r"566... % (a, e))567...568>>> class Color(DuplicateFreeEnum):569... red = 1570... green = 2571... blue = 3572... grene = 2573...574Traceback (most recent call last):575...576ValueError: aliases not allowed in DuplicateFreeEnum: 'grene' --> 'green'577```578579> **Примечание**580>581> Это полезный пример наследования от Enum для добавления или изменения других поведений, а также запрета псевдонимов. Если единственное желаемое изменение – запрет псевдонимов, вместо этого можно использовать декоратор [`unique()`](https://python-all.ru/3.4/library/enum.html#enum.unique).582583### 8.13.13.4. Planet584585Если определены [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) или [`__init__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__init__), значение члена перечисления будет передано этим методам:586587```python588>>> class Planet(Enum):589... MERCURY = (3.303e+23, 2.4397e6)590... VENUS = (4.869e+24, 6.0518e6)591... EARTH = (5.976e+24, 6.37814e6)592... MARS = (6.421e+23, 3.3972e6)593... JUPITER = (1.9e+27, 7.1492e7)594... SATURN = (5.688e+26, 6.0268e7)595... URANUS = (8.686e+25, 2.5559e7)596... NEPTUNE = (1.024e+26, 2.4746e7)597... def __init__(self, mass, radius):598... self.mass = mass # в килограммах599... self.radius = radius # в метрах600... @property601... def surface_gravity(self):602... # гравитационная постоянная (м3 кг-1 с-2)603... G = 6.67300E-11604... return G * self.mass / (self.radius * self.radius)605...606>>> Planet.EARTH.value607(5.976e+24, 6378140.0)608>>> Planet.EARTH.surface_gravity6099.802652743337129610```611612## 8.13.14. Чем отличаются перечисления?613614Перечисления имеют собственный метакласс, который влияет на многие аспекты как производных классов Enum, так и их экземпляров (членов).615616### 8.13.14.1. Классы перечислений617618Метакласс `EnumMeta` отвечает за предоставление методов [`__contains__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__contains__), [`__dir__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__dir__), [`__iter__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__iter__) и других, которые позволяют выполнять с классом [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) действия, невозможные для обычного класса, например *list(Color)* или *some\_var in Color*. `EnumMeta` отвечает за то, чтобы различные другие методы в итоговом классе [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) были корректны (например, [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__), [`__getnewargs__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs__), [`__str__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__str__) и [`__repr__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__repr__)).619620### 8.13.14.2. Члены перечисления (экземпляры)621622Самое интересное в членах Enum – то, что они являются синглтонами. `EnumMeta` создаёт их все во время создания самого класса [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum), а затем устанавливает собственную реализацию [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__), чтобы гарантировать, что новые экземпляры никогда не будут созданы – возвращаются только существующие экземпляры членов.623624### 8.13.14.3. Тонкости625626Члены Enum являются экземплярами класса Enum, и хотя к ним можно обратиться как *EnumClass.member*, они не доступны напрямую из самого члена:627628```python629>>> Color.red630<Color.red: 1>631>>> Color.red.blue632Traceback (most recent call last):633...634AttributeError: 'Color' object has no attribute 'blue'635```636637Аналогично, `__members__` доступен только на уровне класса.638639Если добавить в подкласс [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) дополнительные методы, как в классе [Planet](https://python-all.ru/3.4/library/enum.html#planet) выше, эти методы будут отображаться в [`dir()`](https://python-all.ru/3.4/library/functions.html#dir) члена, но не класса:640641```python642>>> dir(Planet)643['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']644>>> dir(Planet.EARTH)645['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']646```647648Метод [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) будет использоваться только для создания членов [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum) – после этого он заменяется. Любой пользовательский метод [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) должен создать объект и соответствующим образом установить атрибут `_value_`.649650Если вы хотите изменить способ поиска членов [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum), вы должны либо написать вспомогательную функцию, либо определить [`classmethod()`](https://python-all.ru/3.4/library/functions.html#classmethod) для подкласса [`Enum`](https://python-all.ru/3.4/library/enum.html#enum.Enum).651