【问题标题】:Python: is it possible to mix generator and a recursive function?Python:可以混合生成器和递归函数吗?
【发布时间】:2010-07-18 19:39:27
【问题描述】:

有没有办法让下面的代码工作?

add = lambda n: (yield n) or add(n+1)

(答案不需要是函数式的)

【问题讨论】:

  • 你希望它做什么?

标签: python generator recursion


【解决方案1】:
def add(n):
    yield n
    for m in add(n+1):
        yield m

使用递归生成器很容易构建复杂的回溯器:

def resolve(db, goals, cut_parent=0):
    try:
        head, tail = goals[0], goals[1:]
    except IndexError:
        yield {}
        return
    try:
        predicate = (
            deepcopy(clause)
                for clause in db[head.name]
                    if len(clause) == len(head)
        )
    except KeyError:
        return
    trail = []
    for clause in predicate:
        try:
            unify(head, clause, trail)
            for each in resolve(db, clause.body, cut_parent + 1):
                for each in resolve(db, tail, cut_parent):
                    yield head.subst
        except UnificationFailed:
            continue
        except Cut, cut:
            if cut.parent == cut_parent:
                raise
            break
        finally:
            restore(trail)
    else:
        if is_cut(head):
            raise Cut(cut_parent)

...

for substitutions in resolve(db, query):
    print substitutions

这是一个由递归生成器实现的 Prolog 引擎。 db 是一个表示 Prolog 事实和规则数据库的字典。 unify() 是为当前目标创建所有替换并将更改附加到跟踪的统一函数,以便以后可以撤消它们。 restore() 执行撤消操作,is_cut() 测试当前目标是否为 '!',以便我们进行分支修剪。

【讨论】:

  • 给出的添加示例没有终止条件。你是故意的吗?
【解决方案2】:

我不确定“yield(n) 或 add(n+1)”的意图,但递归生成器肯定是可能的。您可能需要阅读下面的链接以了解可能的情况,尤其是标题为“递归生成器”的部分。

【讨论】:

    【解决方案3】:

    在我看来,您的函数只是未绑定序列的其他表达式:

    n, n+1, n+2,....

    def add(x):
        while True:
            yield x
            x+=1
    
    for index in add(5):
        if not index<100: break ## do equivalent of range(5,100)
        print(index)
    

    这不是递归的,但我认为这里不需要递归样式。

    基于其他答案链接的递归版本,它有生成器调用生成器,但不是递归的:

    from __future__ import generators
    
    def range_from(n):
        yield n
        for i in range_from(n+1):
            yield i
    
    for i in range_from(5):
        if not i<100: break ## until 100 (not including)
        print i
    

    【讨论】:

      猜你喜欢
      • 2016-11-10
      • 1970-01-01
      • 2016-12-22
      • 2016-04-03
      • 1970-01-01
      • 2023-03-24
      • 2012-12-30
      • 2012-01-14
      相关资源
      最近更新 更多