Существует ли способ сделать что-то как следующая работа кода?
add = lambda n: (yield n) or add(n+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
Это механизм Пролога, реализованный с помощью рекурсивного генератора. db - это dict, представляющий базу данных фактов и правил Пролога. unify () - это функция объединения, которая создает все замены для текущей цели и добавляет изменения в след, чтобы их можно было отменить позже. restore () выполняет отмену, а is_cut () проверяет, является ли текущая цель «!», чтобы мы могли выполнить обрезку веток.
Я не уверен в намерении «yield (n) или add (n + 1)», но рекурсивные генераторы, безусловно, возможны. Возможно, вы захотите прочитать ссылку ниже, чтобы понять, что возможно, в частности, раздел под названием «Рекурсивные генераторы».
Ваша функция мне кажется просто другим выражением для несвязанной последовательности:
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