问候,目前我正在重构我的一个程序,我发现了一个有趣的问题。
我在自动机中有过渡。转换总是有一个开始状态和一个结束状态。一些转换有一个标签,它对遍历时必须执行的某个动作进行编码。没有标签就意味着没有行动。一些转换有一个条件,必须满足才能遍历这个条件,如果没有条件,则转换基本上是 NFA 中的 epsilon-transition 并且将在不消耗输入符号的情况下进行遍历。
我需要以下操作:
- 检查转换是否有标签
- 得到这个标签
- 为过渡添加标签
- 检查转换是否有条件
- 得到这个条件
- 检查平等
从前五点来看,这听起来像是一个清晰的装饰器,有一个基本的过渡和两个装饰器:Labeled 和 Condition。但是,这种方法有一个问题:如果两个转换的开始状态和结束状态相同,则两个转换被认为是相等的,两个转换处的标签相等(或不存在)并且两个条件相同(或不存在) . 使用装饰器,我可能有两个转换 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 在这种大小下会令人困惑。
当然,第三种选择是将所有东西都锤入一个带有一堆 in has_label/has_transition 的转换类中。
所以......我很困惑。我错过了什么吗?哪个实现看起来更好?你如何处理类似的情况,即看起来像装饰器的对象可以处理它们,但是,这样的非本地方法出现了?
编辑:添加了 ConditionalTransition 类。基本上,这有点像装饰器,减去创建装饰器的顺序,过渡检查开始和结束是否正确,LabeledTransition 类检查标签是否正确,ConditionalTransition 检查条件是否正确。