Ответ 1
Я недавно опубликовал пакет с открытым исходным кодом PY-флаги, что цели этой проблемы. Эта библиотека имеет именно эту функциональность, и ее дизайн сильно зависит от модуля переименования python3.
Есть дебаты о том, достаточно ли для pythonic реализовать такой класс флагов, поскольку его функциональность имеет огромные совпадения с другими методами, предоставляемыми языком (коллекция переменных bool, наборов, объектов с атрибутами bool или dicts с элементами bool,...), По этой причине я считаю, что класс флагов слишком узкий и/или избыточный, чтобы пробиваться к стандартной библиотеке, но в некоторых случаях он намного лучше, чем ранее перечисленные решения, поэтому наличие библиотеки "pip install" -able может пригодиться.
Ваш пример будет выглядеть следующим образом, используя модуль py-flags:
from flags import Flags
class NetlistKind(Flags):
Unknown = 0
LatticeNetlist = 1
QuartusNetlist = 2
XSTNetlist = 4
CoreGenNetlist = 8
All = 15
Вышеуказанные вещи можно было бы еще немного улучшить, поскольку класс флагов, объявленный в библиотеке, автоматически предоставляет два "виртуальных" флага: NetlistKind.no_flags
и NetlistKind.all_flags
. Они делают уже объявленные NetlistKind.Unknown
и NetlistKind.All
избыточными, поэтому мы можем оставить их вне декларации, но проблема в том, что no_flags
и all_flags
не соответствуют вашему соглашению об именах. Чтобы помочь этому, мы объявляем базовый класс флагов в вашем проекте, а не flags.Flags
и вам придется использовать это в остальной части вашего проекта:
from flags import Flags
class BaseFlags(Flags):
__no_flags_name__ = 'Unknown'
__all_flags_name__ = 'All'
Основываясь на ранее объявленном базовом классе, который может быть подклассифицирован любым из ваших флагов в вашем проекте, мы могли бы изменить объявление вашего флага:
class NetlistKind(BaseFlags):
LatticeNetlist = 1
QuartusNetlist = 2
XSTNetlist = 4
CoreGenNetlist = 8
Таким образом NetlistKind.Unknown
автоматически объявляется с нулевым значением. NetlistKind.All
также существует, и он автоматически представляет собой комбинацию всех ваших объявленных флагов. Можно итерации перечислять члены с/без этих виртуальных флагов. Вы также можете объявлять псевдонимы (флаги, которые имеют то же значение, что и ранее объявленный флаг).
В качестве альтернативного объявления, использующего "стиль функционального вызова" (также предоставляемый стандартным модулем enum):
NetlistKind = BaseFlags('NetlistKind', ['LatticeNetlist', 'QuartusNetlist',
'XSTNetlist', 'CoreGenNetlist'])
Если класс flags объявляет некоторые члены, то он считается окончательным. Попытка подкласса приведет к ошибке. Семантически нежелательно разрешать подкласс класса флага с целью добавления новых членов или изменения функциональных возможностей.
Помимо этого, класс flags предоставляет операторы, перечисленные вами (операторы bool, in, iteration и т.д.) Безопасным образом. Я собираюсь закончить README.rst вместе с небольшой настройкой интерфейса пакета в ближайшие несколько дней, но базовые функции уже есть и протестированы с неплохим охватом.