class Child:
@property
def attribute(self):
return 1
class Parent:
def __init__(self):
self.left = Child()
self.right = Child()
@property
def attribute(self):
return self.left.attribute + self.right.attribute
if __name__ == '__main__':
tree = Parent()
print(tree.attribute)
我想用命令式样式替换递归。这不是问题,我做了这个程序:
from inspect import signature
class Child:
def attribute(self, context):
context.execute(lambda: 3)
class Parent:
def __init__(self):
self.left = Child()
self.right = Child()
def attribute(self, context):
context.execute(lambda l, r:
l + r
)
context.evaluate(self.left, Child.attribute.__name__)
context.evaluate(self.right, Child.attribute.__name__)
class Context:
def __init__(self):
self.__evaluation_stack = []
self.__value_stack = []
def evaluate(self, tree, attribute):
self.__evaluation_stack.append(('attr', tree, attribute))
def compute(self):
while self.__evaluation_stack:
cur = self.__evaluation_stack.pop()
if cur[0] == 'attr':
getattr(cur[1], cur[2])(self)
if cur[0] == 'lambda':
count_of_parameters = len(signature(cur[1]).parameters)
params = []
if count_of_parameters > 0:
params = self.__value_stack[-count_of_parameters:]
del self.__value_stack[-count_of_parameters:]
val = cur[1](*params)
self.__value_stack.append(val)
return self.__value_stack.pop()
def execute(self, what):
self.__evaluation_stack.append(('lambda', what))
if __name__ == '__main__':
context = Context()
tree = Parent()
context.evaluate(tree, Parent.attribute.__name__)
result = context.compute()
print(result)
元组的使用只是说明。我稍后会用多态或其他东西替换它。此外,上下文方法将具有更好的名称和可能链接,因此代码看起来不会那么糟糕。
现在,为什么我需要你的帮助。如您所见,正文已更改(节点必须在Context上调用特定方法,并且评估为lambda)。有没有一种本地方式(意思是装饰器或Python可以提供的任何方式)使用递归(或非常类似)语法,它将使用引擎盖下的上下文?
主要问题是,方法需要在执行过程中停止并等待结果。必须提供结果并继续执行。例如,我知道JavaScript中的迭代器可以中断执行,您也可以传递值(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Advanced_generators)。 Python中类似的东西?
实例:https://repl.it/@PatrikValkovic/ImperativeRecursion-EventDriven
EDIT1 - 生成器
我尝试使用发电机,看起来好多了。代码如下,以及链接到实时版本。好的是,Context不使用反射并只保留一个值,而不是堆栈。也许有人可以带更多类似递归的版本?
链接:https://repl.it/@PatrikValkovic/ImperativeRecursion-Generators
class Child:
def attribute(self):
return 3
yield
class Parent:
def __init__(self):
self.left = Child()
self.right = Child()
def attribute(self):
left_value = yield self.left.attribute
right_value = yield self.right.attribute
return left_value + right_value
class Context:
def __init__(self):
self.__evaluation_stack = []
self.__value = None
def evaluate(self, attr):
self.__evaluation_stack.append(attr())
while self.__evaluation_stack:
try:
working = self.__evaluation_stack.pop()
resp = working.send(self.__value) if self.__value else next(working)
self.__value = None
self.__evaluation_stack.append(working)
self.__evaluation_stack.append(resp())
except StopIteration as e:
self.__value = e.value
return self.__value
context = Context()
tree = Parent()
result = context.evaluate(tree.attribute)
print(result)