Python: действительно ли возможно смешать генератор и рекурсивную функцию?

Существует ли способ сделать что-то как следующая работа кода?

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

(ответы не должны быть в функциональном стиле),

5
задан Bayard Randel 18 July 2010 в 21:22
поделиться

3 ответа

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

Это механизм Пролога, реализованный с помощью рекурсивного генератора. db - это dict, представляющий базу данных фактов и правил Пролога. unify () - это функция объединения, которая создает все замены для текущей цели и добавляет изменения в след, чтобы их можно было отменить позже. restore () выполняет отмену, а is_cut () проверяет, является ли текущая цель «!», чтобы мы могли выполнить обрезку веток.

3
ответ дан 14 December 2019 в 13:25
поделиться

Я не уверен в намерении «yield (n) или add (n + 1)», но рекурсивные генераторы, безусловно, возможны. Возможно, вы захотите прочитать ссылку ниже, чтобы понять, что возможно, в частности, раздел под названием «Рекурсивные генераторы».

3
ответ дан 14 December 2019 в 13:25
поделиться

Ваша функция мне кажется просто другим выражением для несвязанной последовательности:

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
0
ответ дан 14 December 2019 в 13:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: