使用递归语法命令替换递归

时间:2018-03-08 10:45:29

标签: python python-3.x recursion decorator python-decorators

虽然我知道,标题很奇怪,我不知道如何更好地描述问题。可以说,我有树,我在那里递归计算属性。简单的例子:

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)

0 个答案:

没有答案