正常的可迭代类存在可能耗尽的问题。我遇到了不同类型的解决方案,但每个解决方案都有不同的问题。这是一个简单的例子:
class MyIter:
def __init__(self, n):
self.n = n
def __iter__(self):
return self
def __next__(self):
self.n /= 2
if self.n < 1:
raise StopIteration
return self.n
x = MyIter(100)
print(list(x))
print(list(x))
你会得到:
[50.0, 25.0, 12.5, 6.25, 3.125, 1.5625]
[]
您可以通过更改该类,并在返回__iter__()
之前将其重置为原始状态来避免这种情况:
class MyRepeatableIter:
def __init__(self, n):
self.n = n
def __iter__(self):
self.current_value = self.n
return self
def __next__(self):
self.current_value /= 2
if self.current_value < 1:
raise StopIteration
return self.current_value
但这仍然无效:
y = MyRepeatableIter(100)
for i, j in zip(y, y):
print(i, j)
你得到:
50.0 25.0
12.5 6.25
3.125 1.5625
如果尝试在线程中使用此迭代器,或者替换使用两个迭代器的代码,则会遇到相同的问题。
我知道的最佳解决方案是返回对象(或副本)的新实例,但如果你的课程足够大,你就会遇到内存问题。
class MyIter:
def __init__(self, n):
self.n = n
def __iter__(self):
return MyIter(self.n)
def __next__(self):
self.n /= 2
if self.n < 1:
raise StopIteration
return self.n
我很好奇哪个被认为是这个问题的最佳解决方案,没有讨论任何问题(没有副本和交替迭代器)
答案 0 :(得分:0)
如果您希望您的实例像发电机一样运行,那么只能实施__next__
,因此无法使用。在这里,你想要的是MyIter.__iter__
返回一个生成器,否则改变实例的任何东西都会影响迭代。
class MyIter:
def __init__(self, n):
self.n = n
def __iter__(self):
n = self.n
while n >= 1:
yield n
n /= 2
obj = MyIter(10)
list(obj) # [10, 5.0, 2.5, 1.25]
list(obj) # [10, 5.0, 2.5, 1.25]
另请注意,__next__
的类实例不会出现问题。实际上,使itertools.product
这样的类如此有用的原因。