我使用使用可再填充器的发电机有问题。
这是我的简单发电机:
def hi(iterable):
for val in iterable:
yield val
我进入HI发电机是函数pipes repo的储层类,它可以在耗尽其元素后重新填充。
我想消耗HI发电机,直到升高停止,然后再重新填充峰值,然后再次消耗
refillable = Reservoir((1, 2, 3, 4))
hi_iter = hi(refillable)
print(tuple(hi_iter))
refillable((5, 6, 7, 8))
print(tuple(hi_iter))
但这打印
(1, 2, 3, 4)
()
第二个元组也应为(5、6、7、8(。
我发现的唯一解决方案是用类包装HI Generator
def super_gener(function):
class wrapper_class:
def __init__(self, iterable):
self.iterable = iterable
self.zipped = None
def __iter__(self):
return self
def __next__(self):
try:
return next(self.zipped)
except TypeError:
self.zipped = function(self.iterable)
return next(self)
except StopIteration as err:
self.zipped = None
raise err
return wrapper_class
hi_iter = super_gener(hi)(refillable)
print(tuple(hi_iter))
refillable(data)
print(tuple(hi_iter))
这个解决方案似乎有点过大,我正在寻找一个更简单的解决方案。感谢您的帮助。
响应ptank:我无法将元素保存到元组中,因为峰值并不总是产生相同的项目,并且在第二次填充可再填充之前,这些项目是不知道的。
我恐怕唯一的解决方案可能是创建可再填充的生成器包装类。编辑:原始未经测试的代码不起作用。我现在已经重新分配了下面的想法并对其进行了测试。
此对象将升高StopIteration
一次,之后它将重新启动。它旨在与Resettable
装饰器一起使用,该装饰器将_func
属性添加到类中。它应该具有原始发电机的所有功能。
class ResettableGenerator():
'''Generator wrapper that is resettable.'''
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self.start()
def __next__(self):
n = self.send(None)
return n
def __iter__(self):
yield from self._gen
def start(self):
self._gen = self._func(*self.args, **self.kwargs)
def send(self, *args, **kwargs):
try:
n = self._gen.send(*args, **kwargs)
return n
except StopIteration:
self.start()
raise
def throw(self, *args, **kwargs):
self._gen.throw(*args, **kwargs)
def close(self):
self._gen.close()
这是装饰器:
def Resettable(some_func):
cls = type(some_func.__name__, (ResettableGenerator,), {})
cls._func = staticmethod(some_func)
return cls
这样使用:
@Resettable
def f():
yield 1
现在您可以做这样的事情:
>>> g=f()
>>> next(g)
1
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __next__
File "<stdin>", line 16, in send
StopIteration
>>> next(g)
1 # generator has restarted itself
您可能能够更新hi
为发电机工厂,并在每次使用时称其为"发电机工厂"。这比您当前的解决方案更干净,但出于其他原因可能无法使用。
def hi(iterable):
def wrapper():
for val in iterable:
yield val
return wrapper
使用与当前使用的使用类似:
refillable = Reservoir((1, 2, 3, 4))
hi_iter = hi(refillable)
print(tuple(hi_iter())) # (1, 2, 3, 4)
refillable((5, 6, 7, 8))
print(tuple(hi_iter())) # (5, 6, 7, 8)
如果要保持与原始示例完全相同的语法,则可以创建一个类似的薄类。
class hi:
def __init__(self, iterable):
self.__iter__ = lambda: iterable
因为发电机不介质,生成器的产生是无记忆的,并且只能读取一次。
只使用元组
def hi(iterable):
return tuple(iterable)