为何自定义生成器类无法生成迭代器?Python迭代对象异常问题
问题分析与解决
嘿,我一眼就瞅出问题所在啦!你的代码里Generator类的写法完全偏离了迭代器/生成器的正确用法——你把生成器逻辑塞到了__init__构造函数里,但__init__根本不能作为生成器使用,而且这个类也没实现迭代器必需的协议,自然没法返回有效的迭代器。
为什么原代码会报错?
当你调用Generator(self.word)时,只是创建了一个Generator类的普通实例,而非生成器迭代器。因为:
__init__是构造函数,它的职责是初始化实例,即便你在里面写了yield,Python也不会把它当成生成器函数处理,反而会忽略这个yield(毕竟构造函数应该返回None,不能返回生成器对象)。- 这个
Generator实例既没有实现__iter__方法来返回自身,也没有__next__方法来提供迭代逻辑,完全不符合迭代器协议,所以调用it.__next__()时必然会抛出异常。
两种修正方案
方案1:直接在Obj的__iter__里写生成器逻辑(最简洁)
不用单独搞Generator类,直接把生成器逻辑放在__iter__方法里就行,因为__iter__本身可以是生成器函数:
#!/usr/bin/env python3 class Obj(): def __init__(self, word): self.word = word def __iter__(self): # 这里直接作为生成器函数,返回迭代器 for l in self.word: yield l obj = Obj('qwe') it = iter(obj) print(it.__next__()) # 输出 q print(it.__next__()) # 输出 w print(it.__next__()) # 输出 e
方案2:正确实现Generator类(保留类结构的话)
如果你一定要保留Generator类的结构,那得让它符合可迭代对象的要求——要么让它的__iter__方法返回生成器,要么手动实现迭代器的__next__方法:
方式A:让Generator的__iter__返回生成器
#!/usr/bin/env python3 class Obj(): def __init__(self, word): self.word = word def __iter__(self): return Generator(self.word) class Generator(): def __init__(self, word): self.word = word def __iter__(self): # 在这里定义生成器逻辑 for l in self.word: yield l obj = Obj('qwe') it = iter(obj) print(it.__next__()) print(it.__next__()) print(it.__next__())
方式B:手动实现迭代器协议
#!/usr/bin/env python3 class Obj(): def __init__(self, word): self.word = word def __iter__(self): return Generator(self.word) class Generator(): def __init__(self, word): self.chars = list(word) self.current_index = 0 def __iter__(self): # 迭代器的__iter__返回自身 return self def __next__(self): # 实现迭代逻辑,到末尾抛出StopIteration if self.current_index >= len(self.chars): raise StopIteration char = self.chars[self.current_index] self.current_index += 1 return char obj = Obj('qwe') it = iter(obj) print(it.__next__()) print(it.__next__()) print(it.__next__())
内容的提问来源于stack exchange,提问作者sergK
相关产品推荐
相关产品推荐

