注:として使用
class Sequential(Enum):
A = 1
B = 2
C = 4
D = 8
E = 16
def succ(self):
v = self.value * 2
if v > 16:
raise ValueError('Enumeration ended')
return Sequential(v)
def pred(self):
v = self.value // 2
if v == 0:
raise ValueError('Enumeration ended')
return Sequential(v)
:
>>> import myenums
>>> myenums.Sequential.B.succ()
<Sequential.C: 4>
>>> myenums.Sequential.B.succ().succ()
<Sequential.D: 8>
>>> myenums.Sequential.B.succ().succ().pred()
<Sequential.C: 4>
明らかにこれはあなたが実際に計算するための簡単な方法を持っている場合にのみ効率的ですアイテムから次のアイテムまたは前のアイテムへの値。これは常にそうであるとは限りません。
スペースを追加するだけで効率的な一般的なソリューションが必要な場合は、後継関数と先行関数のマッピングを作成できます。あなたは(Enum
台無しアップ属性以降)クラスの後に作成を属性としてこれらを追加する必要がありますので、あなたはそれを行うためにデコレータを使用することができます :
として使用
def add_succ_and_pred_maps(cls):
succ_map = {}
pred_map = {}
cur = None
nxt = None
for val in cls.__members__.values():
if cur is None:
cur = val
elif nxt is None:
nxt = val
if cur is not None and nxt is not None:
succ_map[cur] = nxt
pred_map[nxt] = cur
cur = nxt
nxt = None
cls._succ_map = succ_map
cls._pred_map = pred_map
def succ(self):
return self._succ_map[self]
def pred(self):
return self._pred_map[self]
cls.succ = succ
cls.pred = pred
return cls
@add_succ_and_pred_maps
class MyEnum(Enum):
A = 0
B = 2
C = 8
D = 18
:
>>> myenums.MyEnum.A.succ()
<MyEnum.B: 2>
>>> myenums.MyEnum.B.succ()
<MyEnum.C: 8>
>>> myenums.MyEnum.B.succ().pred()
<MyEnum.B: 2>
>>> myenums.MyEnum._succ_map
{<MyEnum.A: 0>: <MyEnum.B: 2>, <MyEnum.C: 8>: <MyEnum.D: 18>, <MyEnum.B: 2>: <MyEnum.C: 8>}
あなたはおそらくKeyError
の代わりにカスタム例外が必要ですが、あなたはそのアイデアを得るでしょう。
はおそらく、メタクラスを使用して、最後のステップを統合する方法があるが、それはEnum
sがメタクラスを使用して実装されており、それがメタクラスを構成するために些細ではないという単純な事実のためにnotstraightforwardです。あなたのnext
とprev
方法(またはsucc
とpred
)を追加する
Pythonで 'enum'の目的はマジックナンバー」の代わりに使用することができるデータの種類を提供することです実際には列挙可能な集合に対応する数学的データ型を提供するわけではありません。したがって、Haskellの 'enum'の目的は若干異なります。いずれにしても、 'myEnum'のメソッドとして' pred'と 'succ'を実装することはできません。 – Bakuriu
その質問の答えの簡単な翻訳を提供しました。 –