本文主要探讨下列三种方法:
object.__iter__(self)
此方法在需要为容器创建迭代器时被调用。此方法应该返回一个新的迭代器对象,它能够逐个迭代容器中的所有对象。对于映射,它应该逐个迭代容器中的键。
迭代器对象也需要实现此方法;它们需要返回对象自身。object.__reversed__(self)
此方法(如果存在)会被 reversed内置函数调用以实现逆向迭代。它应当返回一个新的以逆序逐个迭代容器内所有对象的迭代器对象。object.__next__(self)
从容器中返回下一项。 如果已经没有项可返回,则会引发 StopIteration 异常。
iter 与 next
例子
class MyNumbers:
def __init__(self):
pass
def __iter__(self):
self.a=0
return self
def __next__(self):
x=self.a+1
if self.a>=5:
raise StopIteration
self.a+=1
return x
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)
运行结果
1
2
3
4
5
reversed与next
代码如下:
class MyNumbers:
def __init__(self):
pass
def __reversed__(self):
self.a=0
return self
def __next__(self):
x=5-self.a
if self.a>=5:
raise StopIteration
self.a+=1
return x
myclass = MyNumbers()
myrv=reversed(myclass)
print(next(myrv))
print(next(myrv))
print(next(myrv))
print(next(myrv))
print(next(myrv))
# 以下代码不能运行,会报错
# TypeError: 'MyNumbers' object is not iterable
# for i in myrv:
# print(i)
返回结果
5
4
3
2
1
为什么用 for in 的方法会报错呢?
主要因为in后面要跟迭代器,而该类没有实现迭代器的方法,即iter。当直接使用next() 方法时,会调用类中的函数next,所以不会报错 。当然,你也可以在reversed函数中,生成所需要的迭代器并返回,这样就可以使用for in这种遍历方法 。
iter、reversed和next
class MyNumbers:
def __init__(self):
self.flag=True
pass
def __iter__(self):
self.a=0
return self
def __reversed__(self):
self.a=0
self.flag=not self.flag
return self
def __next__(self):
if self.flag:
x=self.a+1
if self.a>=5:
raise StopIteration
else:
x=5-self.a
if self.a>=5:
raise StopIteration
self.a+=1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print('iter-next')
for x in myiter:
print(x)
print('reversed-next')
myrv=reversed(myclass)
print(next(myrv))
print(next(myrv))
print(next(myrv))
print(next(myrv))
print(next(myrv))
print('reversed-reversed')
myrv=reversed(myclass)
for i in myrv:
print(i)
运行结果
iter-next
1
2
3
4
5
reversed-next
5
4
3
2
1
reversed-reversed
1
2
3
4
5
本例中直接实现了iter和reversed 两种方法。主要设置一个标志位,通过reversed改变标志位来设置是正序输出还是反序输出,通过多次调用reversed可以进行反转。
在执行for in前执行reversed的时候实现调用顺序是reversed->iter->next->next->...