class test(object):
def __init__(self):
pass
def __iter__(self):
return "my string"
o = test()
print iter(o)
Run Code Online (Sandbox Code Playgroud)
为什么这会追溯?
$ python iter_implement.py
Traceback (most recent call last):
File "iter_implement.py", line 9, in <module>
print iter(o)
TypeError: iter() returned non-iterator of type 'str'
Run Code Online (Sandbox Code Playgroud)
我希望__iter__在这种情况下只返回字符串.何时以及为什么检测到返回的对象不是迭代器对象?
str是一个可迭代但不是迭代器,微妙但重要的区别.请参阅此答案以获得解释.
你想要返回一个对象__next__(或者只是next当py2),这str是迭代时返回的对象.
def __iter__(self):
return iter("my string")
Run Code Online (Sandbox Code Playgroud)
str 没有实现 __next__
In [139]: s = 'mystring'
In [140]: next(s)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-140-bc0566bea448> in <module>()
----> 1 next(s)
TypeError: 'str' object is not an iterator
Run Code Online (Sandbox Code Playgroud)
但是调用iter会返回迭代器,这是循环调用:
In [141]: next(iter(s))
Out[141]: 'm'
Run Code Online (Sandbox Code Playgroud)
没有__next__(或next在py2)方法返回任何东西你会遇到同样的问题
您可以使用生成器__iter__返回的生成器self:
def gen():
yield 'foo'
gg = gen()
gg is gg.__iter__()
True
gg.__next__()
'foo'
class Something:
def __iter__(self):
return gen()
list(Something())
['foo']
Run Code Online (Sandbox Code Playgroud)
或者你__next__自己实现的类,就像这个类类似于Ops帖子上的类(你还必须处理StopIteration停止循环)
class test:
def __init__(self, somestring):
self.s = iter(somestring)
def __iter__(self):
return self
def __next__(self):
return next(self.s) ## this exhausts the generator and raises StopIteration when done.
In [3]: s = test('foo')
In [4]: for i in s:
...: print(i)
...:
f
o
o
Run Code Online (Sandbox Code Playgroud)
可以通过添加iter()调用来修复代码:
class test(object):
def __init__(self):
pass
def __iter__(self):
return iter("my string")
Run Code Online (Sandbox Code Playgroud)
这是一个示例运行:
>>> o = test()
>>> iter(o)
<iterator object at 0x106bfa490>
>>> list(o)
['m', 'y', ' ', 's', 't', 'r', 'i', 'n', 'g']
Run Code Online (Sandbox Code Playgroud)
原始错误的原因是__iter__的API 声称返回实际的迭代器.在国际热核实验堆()函数进行检查,以确保履行合同.
注意,这种错误检查也发生在其他地方.例如,len()函数检查以确保__len __()方法返回一个整数:
>>> class A:
def __len__(self):
return 'hello'
>>> len(A())
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
len(A())
TypeError: 'str' object cannot be interpreted as an integer
Run Code Online (Sandbox Code Playgroud)