如何在Python中制作重复生成器(如xrange)?例如,如果我这样做:
>>> m = xrange(5)
>>> print list(m)
>>> print list(m)
我两次都得到相同的结果-数字0..4。但是,如果我尝试与yield相同:
>>> def myxrange(n):
... i = 0
... while i < n:
... yield i
... i += 1
>>> m = myxrange(5)
>>> print list(m)
>>> print list(m)
第二次尝试遍历m时,我什么也没回来-空列表。
有没有简单的方法来创建重复的生成器,例如带有yield的xrange或生成器理解?我找到了a workaround on a Python tracker issue,它使用装饰器将生成器转换为迭代器。每次您开始使用它时都会重新启动,即使您上次没有使用所有值也是如此,就像xrange一样。基于相同的想法,我还提出了自己的装饰器,该装饰器实际上返回一个生成器,但是在抛出StopIteration异常后可以重新启动该生成器:
@decorator.decorator
def eternal(genfunc, *args, **kwargs):
class _iterable:
iter = None
def __iter__(self): return self
def next(self, *nargs, **nkwargs):
self.iter = self.iter or genfunc(*args, **kwargs):
try:
return self.iter.next(*nargs, **nkwargs)
except StopIteration:
self.iter = None
raise
return _iterable()
仅使用 yield 和/或生成器理解,是否有更好的方法来解决该问题?还是Python内置的东西?因此,我不需要滚动自己的类和装饰器?
更新资料
comment by u0b34a0f6ae钉住了我的误解的根源:
我的“永恒”功能是通过像迭代器/生成器(
__iter__
返回self)而不是像collection / xrange(__iter__
返回新的迭代器)来完全吠叫错误的树。 最佳答案
不直接。允许生成器用于实现协同例程,资源管理等的灵活性的一部分是,它们始终是一次性的。一旦运行,发电机将无法重新运行。您将必须创建一个新的生成器对象。
但是,您可以创建自己的覆盖__iter__()
的类。它将像可重用的生成器一样工作:
def multigen(gen_func):
class _multigen(object):
def __init__(self, *args, **kwargs):
self.__args = args
self.__kwargs = kwargs
def __iter__(self):
return gen_func(*self.__args, **self.__kwargs)
return _multigen
@multigen
def myxrange(n):
i = 0
while i < n:
yield i
i += 1
m = myxrange(5)
print list(m)
print list(m)
关于python - 如何在Python中制作重复生成器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1376438/