基本クラスEnum
とIntEnum
を知っています。どちらも非常に便利ですが、フラグ操作の機能がありません。これら2つのクラスが私の希望する機能を実装するとは思わない。
例を作ってみましょう:
class NetlistKind(IntEnum):
Unknown = 0
LatticeNetlist = 1
QuartusNetlist = 2
XSTNetlist = 4
CoreGenNetlist = 8
All = 15
ご覧のとおり、この列挙型の算術機能を取得するためにIntEnum
を既に使用しています。すべての値が2のべき乗であることを確認するために@unique
のようなものがあるといいでしょう。これを行うには、enum.uniqueを必要に応じてフォークします。 (All
はそのルールの例外であることを知っています。)
そのような列挙型はどのように使用されますか?
filter = NetlistKind.LatticeNetlist | NetlistKind.QuartusNetlist
アンダーレイのおかげで、intビット操作が可能になり、フィルターの内部値は3になります。
「フィルタYにフラグXが設定されている」関数、またはさらに優れた演算子があると便利です。 x in y
の魔法の関数を追加します。
@unique
class NetlistKind(IntEnum):
Unknown = 0
LatticeNetlist = 1
QuartusNetlist = 2
XSTNetlist = 4
CoreGenNetlist = 8
All = 15
def __contains__(self, item):
return (self.value & item.value) == item.value
使用例:
....
def GetNetlists(self, filter=NetlistKind.All):
for entity in self._entities:
for nl in entity.GetNetlists():
if (nl.kind in filter):
yield nl
def GetXilinxNetlists(self):
return self.GetNetlists(NetlistKind.XSTNetlist | NetlistKind.CoreGenNetlist)
だから質問は:
オープン機能:
__str__
で返します私は最近、この問題を目的としたオープンソースパッケージ py-flags を公開しました。そのライブラリーはまさにこの機能を備えており、その設計はpython3 enumモジュールに大きく影響されます。
その機能が言語によって提供される他のメソッド(bool変数、セット、bool属性を持つオブジェクト、またはbool項目を持つdictsなど)と非常に重複しているため、そのようなフラグクラスを実装するのに十分なPythonicかどうかについては議論があります。 。このため、フラグクラスは目的が狭すぎたり、冗長であったりして標準ライブラリに到達できないと感じていますが、場合によっては、上記のソリューションよりもはるかに優れているため、「pipインストール」が可能なライブラリを使用できます。便利で。
Py-flagsモジュールを使用すると、例は次のようになります。
from flags import Flags
class NetlistKind(Flags):
Unknown = 0
LatticeNetlist = 1
QuartusNetlist = 2
XSTNetlist = 4
CoreGenNetlist = 8
All = 15
ライブラリで宣言されたフラグクラスが2つの「仮想」フラグ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'])
フラグクラスがいくつかのメンバーを宣言する場合、それは最終であると見なされます。サブクラス化しようとすると、エラーになります。新しいメンバーの追加や機能の変更を目的としてフラグクラスをサブクラス化できるようにすることは、意味的に望ましくありません。
これに加えて、フラグクラスはリストされた演算子(ブール演算子、入力、反復など)をタイプセーフな方法で提供します。今後数日でREADME.rstとパッケージインターフェイスの小さな配管を完了する予定ですが、基本的な機能はすでにそこにあり、十分にカバーされてテストされています。