2008-09-24 5 views
2

인사말, 현재 내 프로그램 중 하나를 리팩토링하고 있으며 흥미로운 문제를 발견했습니다.로컬이 아닌 동등한 데코레이터를 구현하는 방법은 무엇입니까?

나는 오토 마톤에 트랜지션을 가지고있다. 전환에는 항상 시작 상태와 종료 상태가 있습니다. 일부 전환에는 순회시 수행해야하는 특정 작업을 인코딩하는 레이블이 있습니다. 레이블이 없으면 아무런 조치도 취하지 않습니다. 일부 전이에는이 조건을 통과하기 위해 충족되어야하는 조건이 있습니다. 조건이 없으면 기본적으로 NFA에서의 엡실론 전환이며 입력 기호를 사용하지 않고 통과합니다.

나는 다음과 같은 작업이 필요합니다 전환이 레이블

  • 이있는 경우

    • 확인 전환이 조건이있는 경우 전환에
    • 확인 레이블을 추가이 레이블
    • 를 얻을 수
    • 이 조건을 얻으십시오
    • 동등성을 확인하십시오

    첫 번째 5 가지 점을 살펴보면, 이것은 기본 전환과 두 개의 데코레이터 인 라벨이 붙은 상태 인 명확한 데코레이터처럼 들립니다. 그러나 두 가지 전환은 시작 상태와 끝 상태가 같고 두 전환의 레이블이 동일하거나 존재하지 않고 두 조건이 동일하거나 존재하지 않으면 두 전환이 동일하게 간주됩니다. . 데코레이터를 사용하면 Labeled ("foo", Conditional ("bar", Transition ("baz", "qux"))와 Conditional ("bar", Labeled ("foo", Transition ("baz ","로컬이 아닌 평등을 필요로하는 qux "))), 즉 장식 모든 데이터를 수집해야하고이를 비교해야 전환이 세트베이스에서 데이터를 수집 :

    class Transition(object): 
        def __init__(self, start, end): 
         self.start = start 
         self.end = end 
        def get_label(self): 
         return None 
        def has_label(self): 
         return False 
        def collect_decorations(self, decorations): 
         return decorations 
        def internal_equality(self, my_decorations, other): 
         try: 
          return (self.start == other.start 
            and self.end == other.end 
            and my_decorations = other.collect_decorations()) 
        def __eq__(self, other): 
         return self.internal_equality(self.collect_decorations({}), other) 
    
    class Labeled(object): 
        def __init__(self, label, base): 
         self.base = base 
         self.label = label 
        def has_label(self): 
         return True 
        def get_label(self): 
         return self.label 
        def collect_decorations(self, decorations): 
         assert 'label' not in decorations 
         decorations['label'] = self.label 
         return self.base.collect_decorations(decorations) 
        def __getattr__(self, attribute): 
         return self.base.__getattr(attribute) 
    

    인가 이 깨끗한 접근? 내가 놓친 게 있니? - 더 이상 클래스 이름 - 협력 다중 상속을 사용

    은 내가이 문제를 해결 할 수 있기 때문에, 대부분의 혼란 스러워요 :

    class Transition(object): 
        def __init__(self, **kwargs): 
         # init is pythons MI-madness ;-) 
         super(Transition, self).__init__(**kwargs) 
         self.start = kwargs['start'] 
         self.end = kwargs['end'] 
        def get_label(self): 
         return None 
        def get_condition(self): 
         return None 
        def __eq__(self, other): 
         try: 
          return self.start == other.start and self.end == other.end 
         except AttributeError: 
          return False 
    
    class LabeledTransition(Transition): 
        def __init__(self, **kwargs): 
         super(LabeledTransition).__init__(**kwargs) 
         self.label = kwargs['label'] 
        def get_label(self): 
         return self.label 
        def __eq__(self): 
         super_result = super(LabeledTransition, self).__eq__(other) 
         try: 
          return super_result and self.label == other.label 
         except AttributeError: 
          return False 
    
    class ConditionalTransition(Transition): 
        def __init__(self, **kwargs): 
         super(ConditionalTransition, self).__init__(**kwargs) 
         self.condition = kwargs['condition'] 
    
        def get_condition(self): 
         return self.condition 
    
        def __eq__(self, other): 
         super_result = super(ConditionalTransition, self).__eq__(other) 
         try: 
          return super_result and self.condition = other.condition 
         except AttributeError: 
          return False 
    
    # ConditionalTransition about the same, with get_condition 
    class LabeledConditionalTransition(LabeledTransition, ConditionalTransition): 
        pass 
    

    이 클래스 LabledConditionalTransition 정확히 예상 다르게 동작으로 - 거기에는 코드가없는 호소하고 I do not는 MI가이 크기로 혼란 스럽다.

    물론 세 번째 옵션은 모든 것을 has_label/has_transition에 묶여있는 단일 전환 클래스로 해머하는 것입니다.

    그래서 ... 혼란 스럽습니다. 내가 놓친 게 있니? 어떤 구현이 더 좋아 보이는가? 비슷한 경우를 처리하는 방법, 즉 Decorator가 처리 할 수있는 것처럼 보이지만 그와 같은 비 국부적 인 메서드가 돌아 오는 개체를 처리하는 방법은 무엇입니까?

    편집 : ConditionalTransition-class가 추가되었습니다. 기본적으로 데코레이터를 생성하는 순서에 의해 생성 된 순서를 제외한 마이너, 시작과 끝의 전환 검사가 올바른지, LabeledTransition 클래스가 레이블이 올바른지 검사하고 ConditionalTransition이 조건이 올바른지 검사합니다.

  • +0

    나에게 보인다. – hop

    답변

    2

    아무도 내 질문을 이해하지 못한다는 것이 분명하다고 생각합니다. 나는 맥락에서 그것을 넣고 그것을 더 짧게하는 것이 좋습니다. 예를 들어, 여기에 파이썬으로 상태 패턴을 구현할 수있는 방법이 있습니다. 아이디어를 얻기 위해 그것을 연구하십시오.

    class State(object): 
        def __init__(self, name): 
         self.name = name 
    
        def __repr__(self): 
         return self.name 
    
    class Automaton(object): 
        def __init__(self, instance, start): 
         self._state = start 
         self.transitions = instance.transitions() 
    
        def get_state(self): 
         return self._state 
    
        def set_state(self, target): 
         transition = self.transitions.get((self.state, target)) 
         if transition: 
          action, condition = transition 
          if condition: 
           if condition(): 
            if action: 
             action() 
            self._state = target 
          else: 
           self._state = target 
         else: 
          self._state = target 
    
        state = property(get_state, set_state) 
    
    class Door(object): 
        open = State('open') 
        closed = State('closed') 
    
        def __init__(self, blocked=False): 
         self.blocked = blocked 
    
        def close(self): 
         print 'closing door' 
    
        def do_open(self): 
         print 'opening door' 
    
        def not_blocked(self): 
         return not self.blocked 
    
        def transitions(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 'door is', automaton.state 
        door.blocked = True 
        automaton.state = door.closed 
        print 'door is', automaton.state 
    

    이 programm에의 출력은 다음과 같습니다 당신은 파이썬에서 자바 코드를 작성하려고하는 것처럼

    door is open 
    closing door 
    door is closed 
    opening door 
    door is open 
    door is open 
    
    0

    게시 된 코드에서 전환 및 라벨 전환의 유일한 차이점은 get_lable() 및 has_label()의 반환입니다.어떤 경우에는 레이블 속성을 없음으로 설정하고 has_label() 함수에서

    return self.label is not None 
    

    의 두 클래스를 압축 할 수 있습니다.

    ConditionalTransition 클래스의 코드를 게시 할 수 있습니까? 나는 이것이 이것이 더 명확해질 것이라고 생각한다.

    관련 문제