Лично я бы изменил свой импорт следующим образом:
from tags import Tags
.. что позволило бы мне ссылаться на элементы перечисления, просто набрав Tags.A
везде с минимальным суетой.
Но если вы действительно хотите продолжать ссылаться на эти элементы из пространства имен модуля, один из подходов состоит в определении __getattr__
функции в tags.py
:
class Tags(enum.Flag):
NONE = 0
A = enum.auto()
B = enum.auto()
C = enum.auto()
def __getattr__(name: str) -> Tags:
return Tags[name]
Во время выполнения Python попытается вызвать эту функцию, если вы попытаетесь получить доступ к некоторому атрибуту, который не был определен напрямую в объекте модуля tags
. Mypy понимает это соглашение и предполагает, что если определено __getattr__
, модуль является «неполным». Таким образом, он будет использовать возвращаемый тип в качестве типа для любых отсутствующих атрибутов, к которым вы пытаетесь получить доступ.
Возможно, вы все равно захотите сделать globals().update(Tags.__members__)
в основном для оптимизации производительности, чтобы пропустить необходимость фактического вызова __getattr__
функция во время выполнения.
Эта стратегия действительно работает только в том случае, если tags.py содержит только одно перечисление - в противном случае вам нужно сделать тип возвращаемого значения что-то вроде Union[Tags, MyOtherEnum]
(что громоздко) или даже просто Any
(что теряет преимущества использования средства проверки типов).
Эта стратегия также означает, что mypy не сможет делать более сложные выводы и сужения типов, принимая во внимание фактическое значение перечисления. Это, в основном, уместно, только если вы используете буквальные перечисления.
Если это проблемы, вам, возможно, придется прибегнуть к более грубому подходу, например:
from typing import TYPE_CHECKING
class Tags(enum.Flag):
NONE = 0
A = enum.auto()
B = enum.auto()
C = enum.auto()
globals().update(Tags.__members__)
if TYPE_CHECKING:
NONE = Tags.NONE
A = Tags.A
B = Tags.B
C = Tags.C
Константа TYPE_CHECKING
всегда ложна во время выполнения, но считается всегда истинной для проверок типов.
Но если вы собираетесь go за счет прямого сообщения mypy о каждом из эти варианты, вы могли бы просто пропустить попытку автоматического обновления глобалов и сделать это вместо этого:
class Tags(enum.Flag):
NONE = 0
A = enum.auto()
B = enum.auto()
C = enum.auto()
NONE = Tags.NONE
A = Tags.A
B = Tags.B
C = Tags.C
Очевидно, что повторять себя дважды, как это, довольно неоптимально, но я не думаю, что есть легкий способ обойти это. Возможно, вы могли бы смягчить это, создав сценарий, который автоматически генерирует tags.py
для вас, но это также довольно неоптимально, просто по разным причинам.