class test(object):
def __init__(self):
pass
def __iter__(self):
return "my string"
o = test()
print iter(o)
为什么会产生回溯?
$ 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'
我希望__iter__
在这种情况下只返回字符串。何时以及为什么检测到返回的对象不是迭代器对象?
答案 0 :(得分:6)
cloneCurrentTree
是可迭代的,但不是迭代器,微妙但重要的区别。有关说明,请参阅此answer。
您想要返回一个str
的对象(如果是py2则只返回__next__
),这是next
在迭代时返回的内容。
str
def __iter__(self):
return iter("my string")
未实施str
__next__
但是调用iter会返回迭代器,这就是循环调用:
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
在没有In [141]: next(iter(s))
Out[141]: 'm'
(或py2中的__next__
)方法的情况下返回任何内容时会遇到同样的问题
您可以使用一个生成器,它本身有next
,返回__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']
的类,就像这个类类似于Ops帖子上的那个类(你还必须处理停止循环的__next__
)
StopIteration
答案 1 :(得分:5)
可以通过添加 iter()调用来修复代码:
class test(object):
def __init__(self):
pass
def __iter__(self):
return iter("my string")
以下是一个示例运行:
>>> o = test()
>>> iter(o)
<iterator object at 0x106bfa490>
>>> list(o)
['m', 'y', ' ', 's', 't', 'r', 'i', 'n', 'g']
原始错误的原因是 __ iter __ 的API声称返回实际的迭代器。 iter()函数检查以确保合同得到满足。
注意,这种错误检查也发生在其他地方。例如, 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
答案 2 :(得分:2)
__iter__
魔术函数的目的是返回可以迭代(例如循环)的东西。最常见的解决方案是返回iter(something)
,其中something
可以是列表,元组,集合,字典,字符串......我们可以迭代的任何内容。看一下这个例子:
class Band:
def __init__(self):
self.members = []
def add_member(self, name):
self.members.append(name)
def __iter__(self):
return iter(self.members)
if __name__ == '__main__':
band = Band()
band.add_member('Peter')
band.add_member('Paul')
band.add_member('Mary')
# Magic of __iter__:
for member in band:
print(member)
输出:
Peter
Paul
Mary
在这种情况下,__iter__
魔术函数允许我们循环遍历band
,就像它是成员集合一样。这意味着在你的情况下,返回&#34;我的字符串&#34;不行。如果你想在&#34;我的字符串&#34;:
def __iter__(self):
return iter("my string") # ==> m, y, ' ', s, t, r, i, n, g
但是,如果你想返回一个包含单个元素的列表&#34;我的字符串&#34;,那么:
def __iter__(self):
return iter(["my string"])
答案 3 :(得分:2)
回答您的具体问题。 Python2似乎检查是否存在.next
类属性:
>>> class test(object):
... next = None
... def __iter__(self):
... return self
...
>>> print iter(test())
<__main__.test object at 0x7fcef75c2f50>
实例属性不会执行:
>>> class test(object):
... def __init__(self):
... self.next = None
... def __iter__(self):
... return self
...
>>> print iter(test())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: iter() returned non-iterator of type 'test'