2


0

ご挨拶、現在私は自分のプログラムの1つをリファクタリングしていますが、興味深い問題を発見しました。

オートマトンに遷移があります。 遷移には常に開始状態と終了状態があります。 一部の遷移にはラベルが付いています。これは、トラバース時に実行する必要がある特定のアクションをエンコードしたものです。 ラベルがない場合は、何もしません。 いくつかの遷移は、この条件を横切るために満たされなければならない条件を有し、条件がない場合、遷移は基本的にNFAにおけるイプシロン遷移であり、入力シンボルを消費することなく横断される。

以下の操作が必要です。

  • 遷移にラベルがあるかどうかを確認

  • このラベルを入手

  • トランジションにラベルを追加する

  • 遷移に条件があるかどうかを確認

  • この状態になる

  • 平等をチェックする

最初の5点から判断すると、これは明確なデコレータのように聞こえます。基本トランジションと2つのデコレータ(LabeledとCondition)があります。 しかし、このアプローチには問題があります。2つの遷移は、開始状態と終了状態が同じで、両方の遷移のラベルが等しい(または存在しない)、両方の条件が同じ(または存在しない)場合は等しいと見なされます。 。 デコレータを使うと、ラベル付きの遷移( "foo"、Conditional( "bar"、Transition( "baz"、 "qux")))とConditional( "bar"、Labeled( "foo"、Transition( "baz))の2つの遷移があります。 "、" qux "))))非局所的な等価性が必要です。つまり、デコレータはすべてのデータを収集する必要があり、遷移は集合ベースでこの収集されたデータを比較する必要があります。

クラス遷移(オブジェクト):デフ__init __(自己、開始、終了):self.start =開始self.end =終了def get_label(自己):戻り値なしdef has_label(自己):戻り値false def collect_decorations(self、decorations):デコレーションを返すdef internal_equality(self、my_decorations、other):return(self.start == other.start and self.end == other.end and my_decorations = other.collect_decorations())def __eq __(self、other): self.internal_equality(self.collect_decorations({})、その他)を返します

ラベルLabeled(オブジェクト):def __init __(self、label、base):self.base = base self.label =ラベルdef has_label(self):戻り値true def get_label(self):戻り値self.label def collect_decorations(self、decorations) ): 'label'をデコレーションに含まれていないと宣言する['label'] = self.label self.base.collect_decorations(decorations)を返すdef __getattr __(self、attribute):self.baseを返す。__getattr(attribute)

これはクリーンなアプローチですか? 私は何かが足りないのですか?

私はこれを解決することができるので、私はほとんど混乱しています - より長いクラス名で - 協調的な多重継承を使う:

クラスTransition(object):def __init __(self、** kwargs):#initはpythonsですMI狂気;-) super(Transition、self).__ init __(** kwargs)self.start = kwargs ['start'] self .end = kwargs ['end'] def get_label(self):戻り値なしdef get_condition(self):戻り値なしdef __eq __(self、other):試してください:self.start == other.startおよびself.end == AttributeErrorを除くother.end:falseを返す

LabeledTransition(遷移):def __init__(self、** kwargs):super(LabeledTransition).__ init__(** kwargs)self.label = kwargs ['ラベル'] def get_label(自己):return self.label def __eq __( self):super_result = super(LabeledTransition、self).__ eq __(その他)try:super_resultとself.label == other.labelを返します。AttributeError以外はfalseを返します。

ConditionalTransition(Transition)クラス:def __init __(self、** kwargs):super(ConditionalTransition、self).__ init __(** kwargs)self.condition = kwargs ['condition']

def get_condition(self):self.conditionを返します。

def __eq __(self、other):super_result = super(ConditionalTransition、self).__ eq __(other)try:return super_resultおよびself.condition = other.condition(AttributeError以外):Falseを返します。

#ConditionalTransitionとほぼ同じ、get_conditionクラスのLabeledConditionalTransition(LabeledTransition、ConditionalTransition):pass

LabledConditionalTransitionクラスは期待通りに振る舞います - そしてそこにコードがないことは魅力的であり、私はMIがこのサイズで混乱することはありません。

もちろん、3番目の選択肢は、in has_label / has_transitionを使って、すべてを1つの遷移クラスにまとめることです。

そう…​ 私は混乱しています。 私は何かが足りないのですか? どの実装が良く見えますか? 似たようなケース、つまりDecoratorのように見えるオブジェクトはどのように処理できますか?しかし、そのようなローカルではないメソッドが発生しますか?

EDIT:ConditionalTransitionクラスを追加しました。 基本的に、この種はデコレータのように振る舞い、デコレータを作成する順序によって作成された順序、開始と終了の遷移チェック、ラベルの正しいLabeledTransitionクラスのチェック、および条件の正しい条件のチェックです。

2 Answer


2


誰もあなたの質問を本当に理解していないのは明らかだと思います。 文脈に入れて短くすることをお勧めします。 例として、これがpythonのstateパターンの一つの可能​​な実装です、アイデアを得るためにそれを研究してください。

クラスState(オブジェクト):def __init __(self、name):self.name = name

def __repr __(self):self.nameを返す

クラスAutomaton(オブジェクト):デフ__init __(自己、インスタンス、開始):self._state =開始self.transitions = instance.transitions()

def get_state(self):自分自身を返す。

def set_state(self、target):遷移=アクションの場合はtransition = self.transitions.get((self.state、target))、条件の場合はcondition =遷移:ifアクションの場合はaction()self._state =それ以外の場合:self._state = targetそれ以外の場合:self._state = target

state = property(get_state、set_state)

クラスDoor(オブジェクト):open = State( 'open')closed = State( 'closed')

def __init __(self、blocked = False):self.blocked = blocked

def close(self): 'ドアを閉める'を印刷する

def do_open(self): 'open door'を印刷する

def not_blocked(self):返されないself.blocked

def transition(self):return {(self.open、self.closed):( self.close、self.not_blocked)、(self.closed、self.open):( self.do_open、self.not_blocked)、}

if __name__ == '__main__':door = Door()automaton = Automaton(door、door.open)

print 'door is'、automaton.state automaton.state = door.closed print 'door is'、automaton.state automaton.state = door.open print 'ドアは'、automaton.state door.blocked = True automaton.state = door.closed print 'door is'、automaton.state

このプログラムの出力は次のようになります。

ドアは開いています閉じていますドアは閉じています開きますドアは開いていますドアは開いています


0


投稿されたコードから、TransitionとLabeled Transitionの唯一の違いはget_lable()とhas_label()の戻りです。 この場合、label属性をNoneと2に設定する2つの単一クラスを圧縮できます。

return self.label is not None

has_label()関数内にあります。

`ConditionalTransition`クラスのコードを投稿できますか? これがもっと明確になると思います。