在python中重置生成器的递归
我试图编写一个函数,返回生成器的下一个元素,如果它在生成器的末尾,它将重置它并返回下一个结果。以下代码的预期输出为:在python中重置生成器的递归,python,recursion,generator,Python,Recursion,Generator,我试图编写一个函数,返回生成器的下一个元素,如果它在生成器的末尾,它将重置它并返回下一个结果。以下代码的预期输出为: 1 2 3 1 2 然而,这显然不是我得到的。我在做什么,这是不正确的 a = '123' def convert_to_generator(iterable): return (x for x in iterable) ag = convert_to_generator(a) def get_next_item(gen, original): try:
1
2
3
1
2
然而,这显然不是我得到的。我在做什么,这是不正确的
a = '123'
def convert_to_generator(iterable):
return (x for x in iterable)
ag = convert_to_generator(a)
def get_next_item(gen, original):
try:
return next(gen)
except StopIteration:
gen = convert_to_generator(original)
get_next_item(gen, original)
for n in range(5):
print(get_next_item(ag,a))
1
2
3
None
None
您需要返回递归调用的结果:
return get_next_item(gen, original)
这仍然不能使这成为一种有效的方法。
重新绑定函数中的局部变量gen
,不会改变for循环中使用的生成器ag
。它会一直精疲力竭
正如评论中所提到的,请检查。
获取下一个\u项
是一个生成器,它返回一个迭代器,通过\uuuuuu下一个\uu
方法为您提供它生成的值。出于这个原因,你的声明没有任何作用
您要做的是:
def get_next_item(gen, original):
try:
return next(gen)
except StopIteration:
gen = convert_to_generator(original)
for i in get_next_item(gen, original):
return i
或更短,且完全等效(只要gen
有\uuuuu iter\uuuu
方法,它可能有):
或者没有递归(这在python中是一个大问题,因为它1.深度有限,2.速度慢):
如果convert_to_generator只是对iter的一个调用,它甚至更短:
def get_next_item(gen, original):
for i in gen:
yield i
while True:
for i in original:
yield i
或者,使用itertools
:
import itertools
def get_next_item(gen, original):
return itertools.chain(gen, itertools.cycle(original))
如果gen
保证是原始
的迭代器,则get\u next\u项目
相当于itertools.cycle
旁注:您可以使用Python 3.3或更高版本将交换为x中的i:yield i
交换为yield from x
(其中x
是一些表达式)。是一种可能的替代方法吗?简单的方法就是使用,否则,如果所述iterable是迭代器(又称生成器),则需要记住iterable中的元素因为这些不能重置,如果它不是迭代器,您可以多次重用它
文档包括一个示例实现
def cycle(iterable):
# cycle('ABCD') --> A B C D A B C D A B C D ...
saved = []
for element in iterable:
yield element
saved.append(element)
while saved:
for element in saved:
yield element
或者,例如,做重用的事情
def cycle(iterable):
# cycle('ABCD') --> A B C D A B C D A B C D ...
if iter(iterable) is iter(iterable): # is a iterator
saved = []
for element in iterable:
yield element
saved.append(element)
else:
saved = iterable
while saved:
for element in saved:
yield element
示例使用
test = cycle("123")
for i in range(5):
print(next(test))
现在关于你的代码,问题很简单,它不记得它的状态
def get_next_item(gen, original):
try:
return next(gen)
except StopIteration:
gen = convert_to_generator(original) # <-- the problem is here
get_next_item(gen, original) #and you should return something here
def get_next_项目(gen,原件):
尝试:
返回下一个(gen)
除停止迭代外:
gen=将_转换为_生成器(原始)#将_转换为_生成器
做什么?请同时发布它的代码。您可能对它感兴趣,它还提供了一个示例实现。我添加了它@Jarvis@VincentSavard提供了答案。实际上我已经试过了。它只开始返回第一个元素1,2,3,1,1
。如果original
为空,则这将陷入一个无限的零循环sequence@Copperfield它应该做什么不同的事情?停止迭代?抛出异常?还是重复最后一个元素?我的代码片段与mnky9800n的代码完全相同。编辑:他想要他的代码做什么。简单,而不是当为真时
do当为原创时
所以如果原创
为真时,它不会陷入无限的虚无循环empty@Copperfield这是一种选择,但我想抛出异常是更好的方法。问题是,它主要是基于意见的。我同意,目前的解决方案是最糟糕的,但它可以扩展以适合使用它的程序员的风格。
test = cycle("123")
for i in range(5):
print(next(test))
def get_next_item(gen, original):
try:
return next(gen)
except StopIteration:
gen = convert_to_generator(original) # <-- the problem is here
get_next_item(gen, original) #and you should return something here