سؤال

تحياتي، أقوم حاليًا بإعادة بناء أحد برامجي، وقد وجدت مشكلة مثيرة للاهتمام.

لدي التحولات في أتمتة.التحولات دائما لها حالة البداية والحالة النهائية.تحتوي بعض التحولات على علامة ترمز إلى إجراء معين يجب تنفيذه عند الاجتياز.عدم وجود تسمية يعني عدم وجود إجراء.تحتوي بعض التحولات على شرط يجب استيفاؤه من أجل اجتياز هذا الشرط، إذا لم يكن هناك شرط، فإن الانتقال هو في الأساس انتقال إبسيلون في NFA وسيتم اجتيازه دون استهلاك رمز الإدخال.

أحتاج إلى العمليات التالية:

  • تحقق مما إذا كان الانتقال يحتوي على تسمية
  • الحصول على هذه التسمية
  • إضافة تسمية إلى التحول
  • تحقق مما إذا كان للانتقال شرط
  • الحصول على هذا الشرط
  • التحقق من المساواة

انطلاقًا من النقاط الخمس الأولى، يبدو هذا بمثابة ديكور واضح، مع انتقال أساسي واثنين من الديكورات:المسمى والحالة.ومع ذلك، فإن هذا النهج لديه مشكلة:يعتبر التحولان متساويين إذا كانت حالة البداية والحالة النهائية لهما هي نفسها، وكانت التسميات في كلا التحولين متساوية (أو غير موجودة) وكلا الشرطين متماثلان (أو غير موجودين).باستخدام الديكور، قد يكون لدي عمليتين انتقاليتين 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 تمامًا كما هو متوقع - وعدم وجود رمز فيه أمر جذاب ولا أعتقد أن MI مربكًا بهذا الحجم.

بالطبع، سيكون الخيار الثالث هو دمج كل شيء في فئة انتقالية واحدة مع مجموعة من has_label/has_transition.

لذا...أنا في حيرة.هل فاتني شيء؟أي تنفيذ يبدو أفضل؟كيف يمكنك التعامل مع الحالات المشابهة، أي الكائنات التي تبدو وكأنها مصممة ديكور يمكنها التعامل معها، ولكن بعد ذلك، تظهر مثل هذه الطريقة غير المحلية؟

يحرر:تمت إضافة فئة الانتقال الشرطي.في الأساس، يتصرف هذا النوع مثل الديكور، مطروحًا منه الترتيب الذي تم إنشاؤه بواسطة ترتيب إنشاء الديكورات، ويتحقق الانتقال من صحة البداية والنهاية، وتتحقق فئة LabeledTransition من صحة التسمية، ويتحقق ConditionalTransition من صحة الشرط.

هل كانت مفيدة؟

المحلول

أعتقد أنه من الواضح أنه لا أحد يفهم سؤالك حقًا.أود أن أقترح وضعه في السياق وجعله أقصر.على سبيل المثال، إليك أحد التطبيقات المحتملة لنمط الحالة في لغة بايثون، يرجى دراستها للحصول على فكرة.

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

مخرجات هذا البرنامج ستكون:

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

نصائح أخرى

من الكود الذي تم نشره، فإن الفرق الوحيد بين الانتقال والانتقال المسمى هو إرجاع get_lable() و has_label().في هذه الحالة، يمكنك ضغط هذين الفصلين في فئة واحدة تقوم بتعيين سمة التسمية على لا شيء و

return self.label is not None

في الدالة has_label().

هل يمكنك نشر الكود الخاص بـ ConditionalTransition فصل؟أعتقد أن هذا سيجعل الأمر أكثر وضوحا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top