为什么类需要定义__iter__()
返回self,以获取类的迭代器?
class MyClass:
def __init__(self):
self.state = 0
def __next__(self):
self.state += 1
if self.state > 4:
raise StopIteration
return self.state
myObj = MyClass()
for i in myObj:
print(i)
控制台日志:
Traceback (most recent call last):
for i in myObj:
TypeError: 'MyClass' object is not iterable
回答https://stackoverflow.com/a/9884259/4515198,
迭代器是具有下一个(Python 2)或
__next__
(Python 3)方法的对象。
添加以下内容的任务:
def __iter__(self):
return self
是返回迭代器,或者是类的对象,它定义了__next__()
方法。
但是,当MyClass在行myObj = MyClass()中实例化时,不是返回已由__next__()
方法完成的MyClass对象(定义{{1}}方法)的任务?
定义__new__()
方法的类的对象不是自己的迭代器吗?
我已经研究了问题What is the use of returning self in the __iter__ method?和Build a Basic Python Iterator,但我仍然无法理解让__next__()
方法返回自我的原因。
答案 0 :(得分:9)
为什么 __ iter __()方法是必要的问题的答案是 for-loops 总是从在对象上调用 iter() 来获取迭代器。这就是为什么即使是iterator也需要一个 __ iter __()方法来处理for循环。在 for 调用 iter()之后,它会在生成的迭代器上调用 __ next __()来获取值。
创建iterables和迭代器的规则是:
1)Iterables有一个返回迭代器的 __ iter __()方法。
2)迭代器有一个 __ next __()方法,它返回一个更新状态的值,并在完成时引发 StopIteration 。
3)迭代器本身有一个返回 self 的 __ iter __()方法。这意味着所有迭代器都是可自我迭代的。
对于具有返回 self 的 __ iter __()方法的迭代器,最后一条规则的好处是它允许我们来传递部分消耗的迭代器:
>>> s = 'hello world'
>>> it = iter(s)
>>> next(it)
'h'
>>> next(it)
'e'
>>> list(it) # Doesn't start from the beginning
['l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
这是另一个依赖于迭代器可以自动迭代而不重新启动的例子:
>>> s = 'hello world'
>>> it = iter(s)
>>> list(zip(it, it))
[('h', 'e'), ('l', 'l'), ('o', ' '), ('w', 'o'), ('r', 'l')]
备注:强>
1)制作可迭代的另一种方法是提供 __ getitem __()方法,该方法接受连续索引并在完成时引发 IndexError 。这就是在Python 2中迭代 str 对象的方式。
2)像文件这样的对象是它们自己的迭代器。这意味着您可以直接在文件对象上调用 next()。它还意味着文件不能有多个独立的迭代器(文件对象本身具有跟踪文件中位置的状态)。
3)上面描述的迭代器设计模式不是Python特有的。它是许多OOP语言的通用设计模式:https://en.wikipedia.org/wiki/Iterator_pattern
答案 1 :(得分:4)
已经由
完成了__new__()
方法
不,__new__
只是另一种方法,它不会自动为对象创建__iter__
。
赢得定义
__next__()
方法的类的对象,自己是迭代器吗?
不一定,因为您定义__next__
而非__iter__
的第一堂课显示。如果您需要支持迭代,则__next__
需要,因为它会生成值。 __iter__
需要for
,因为它在__next__
语句中调用了一个对象,以便它获得一个迭代器。
你可以拥有一个只定义__iter__
并且有些工作(它是有限的)的类,但它需要从某些人MyClass
返回。例如,类CustomIter
返回仅定义__next__
的类class MyClass:
def __iter__(self):
return CustomIter()
class CustomIter(object):
def __init__(self):
self.state = 0
def __next__(self):
self.state += 1
if self.state > 4:
raise StopIteration
return self.state
:
__iter__
您需要在对象上定义__next__
,该对象将返回定义__iter__
的另一个对象(可能是其自身)。
如果您的班级将def __iter__(self): return self
定义为:
__next__
然后您需要在type(self)
(该类)上定义__next__
,因为您返回实例本身。 self
将调用__iter__
,直到无法生成更多值。
另一种情况是__next__
只返回另一个定义__iter__
的对象(根据我的第一个例子)。您也可以通过使class MyClass:
def __init__(self):
self.state = 0
def __iter__(self):
for i in range(10): yield i
生成器来实现。
例如:
__next__
没有定义iter
。当g = iter(MyClass())
被调用时:
g
它返回定义__next__
的生成器g = iter(MyClass())
g.__next__() # 0
g.__next__() # 1
:
vector<int> visited(50001);
map< pair<ll,ll> , ll> mymap;
map<ll, vector<ll> > graph;
void calc(ll start,ll node)
{
visited[node]=1;
vector<ll>::iterator it;
for (it = graph[node].begin(); it != graph[node].end(); ++it)
{
if (!visited[*it])
{
ans+=mymap[make_pair(node,*it)];
mymap[make_pair(start,*it)]=ans;
calc(start, *it);
ans-=mymap[make_pair(node,*it)];
}
}
}