Приветствую вас, в настоящее время я рефакторинг одной из моих программ, и я нашел интересную проблему.Как реализовать декоратор с нелокальным равенством?
У меня есть переходы в автоматах. Переходы всегда имеют начальное состояние и конечное состояние. Некоторые переходы имеют метку, которая кодирует определенное действие, которое должно выполняться при обходе. Никакой ярлык не означает никаких действий. Некоторые переходы имеют условие, которое должно выполняться для прохождения этого условия, если нет условия, переход в основном является эпсилон-переходом в 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)
Is это чистый подход? Я что-то упускаю?
Я в основном путают, потому что я могу решить эту проблему - с более длинными именами классов - с помощью кооперативного множественного наследования:
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.
Итак ... Я смущен. Я что-то упускаю? Какая реализация выглядит лучше? Как вы обрабатываете похожие случаи, то есть объекты, которые выглядят как Decorator, могут справиться с ними, но тогда возникает такой нелокальный метод?
EDIT: Добавлен ConditionalTransition-класс. В принципе, этот вид ведет себя как декоратор, за вычетом порядка, созданного порядком создания декораторов, проверка перехода для начала и конца правильна, класс LabeledTransition проверяет правильность метки и ConditionalTransition проверяет правильность условия.
смотрит на меня, как вы пытаетесь писать код Java в Python. – hop