TGViewer
Находки в опенсорсе Находки в опенсорсе @opensource_findings · 12.6K subscribers
Post #883 9.5K
Enum и сложность

Enum – один из самых сложных модулей в питоне, я не шучу. Количество нюансов – просто огромное. Так как я последние несколько дней занимаюсь улучшением поддержки Enum в mypy, то я решил рассказать про интересные штуки из модуля enum, которые вы скорее всего могли пропустить.

Доки: https://docs.python.org/3/library/enum.html Их все равно никто не читает.

global_enum

Чудовищная фича. Просто ужас. Засовывает все значения Enum в sys.modules[module].__dict__:


>>> from enum import Enum, global_enum

>>> @global_enum
... class Pets(Enum):
... CAT = 1
... DOG = 2

>>> print(CAT)
CAT


Да, создает новые глобальные константы. Нет, mypy такое пока не поддерживает.
Для чего нужно? Синтаксический сахар для обратной совместимости. Когда были раньше CAT и DOG как константы в модуле, а потом появляется Enum. Но все равно не советую.

_simple_enum


>>> from enum import IntEnum, _simple_enum
>>>
>>> @_simple_enum(IntEnum)
... class Pets:
... CAT = 1
... DOG = 2
...
>>> print(Pets.CAT)
1


Специальный внутренний хелпер для более быстрого создания Enum классов. Используется в основном внутри CPython для ускорения импорта библиотек. Не поддерживается mypy.

@unique

Декоратор, который позволит найди дубликаты по значениям в ваших Enum типах и вызвать ошибку. Обязателен для использования. Иначе, где-то можно сделать опечатку:


@unique # <- will find the problem
class Pets(Enum):
CAT = 1
DOG = 1 # should be 2


и искать её всю жизнь.

Flag и FlagBoundary

Зачем нужны Flag?


from enum import IntFlag, FlagBoundary

class Permission(IntFlag, boundary=FlagBoundary.STRICT):
READ = 0
WRITE = 1


Для сочетания друг с другом: Permission.WRITE | Permission.READ. Есть 4 разных поведения для таких случаев: https://docs.python.org/3/library/enum.html#enum.FlagBoundary

Советую всегда использовать FlagBoundary.STRICT, если сомневаетесь.

Черная дыра для багов и изменений от версии к версии.

member и nonmember

В Enum есть довольно сложная логика, какие объекты считать за member (часть enum), какие за nonmember (просто какие-то объекты).
Кратко:
- Имя не приватное, имя не __dunder__ и имя не _sunder_
- Имя не в _ignore_
- Не вложенный класс и не метод
- Не инстанс nonmember

Пример:


from enum import Enum, member, nonmember

class Example(Enum):
_ignore_ = ['a'] # nonmember
a = 1 # nonmember
b = 2 # member
__c__ = 3 # nonmember
_d_ = 4 # nonmember
e = nonmember(5) # nonmember
__f = 6 # nonmember

def g(self): ... # nonmember

@member
def h(self): ... # member


Думаю, что всем спалось спокойнее без такого знания. Старайтесь делать такие енамы, чтобы не приходилось использовать темную магию. И старайтесь не пользоваться member и nonmember.

Enum в .pyi файлах

Недавно Typing Spec для енамов был изменен. https://typing.readthedocs.io/en/latest/spec/enums.html

Раньше в .pyi файлах мы аннотировали енамы так:


# mymodule.pyi
class Pets(Enum):
CAT: int
DOG: int


Однако, теперь такой способ будет создавать два nonmember'а. Правильный способ:


# mymodule.pyi
class Pets(Enum):
CAT = 1
DOG = 2


Почему? Потому что значения полей – крайне важно для типа Enum.
Для старого кода mypy выкидывает ошибку.

Обсуждение: а вам нравились Enum в Python? А сейчас?

| Поддержать | YouTube | GitHub | Чат |
GitHub Properly account for `member` and `nonmember` in `TypeInfo.enum_members` by sobolevn · Pull Request #18559 · python/mypy Closes #18557
  • 🔥 110
  • 👍 58
  • 🤯 36
  • ❤ 14
  • 🕊 3
More from @opensource_findings
  1. Sep 28, 2026Еще анонсы докладов на бесплатную конференцию 17 октября в НН Регистрация: https://itgorky…
  2. Sep 25, 2026Монадические выражения в Python. Наконец-то! Продолжаем разговор про интересные PEPы. Пого…
  3. Sep 15, 2026PEPы в Python окончательно вышли из-под контроля Давайте посмотрим, что происходит с ПЕПам…
  4. Sep 10, 2026Большая бесплатная конференция в Нижнем Новгороде 17 октября Регистрация: https://itgorky.…
  5. Sep 1, 2026Post #985
  6. Aug 24, 2026JIT могут удалить из CPython! PEP-836: https://peps.python.org/pep-0836 JIT в CPython имее…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →