咱都知道, list ,tuple,dict 都是可迭代对象,如果想让他们转化成迭代器.
我们可以这么做,调用 inter()方法,它会返回一个迭代器.
例如:
from collections import Iterable,Iterator
a=[1,2]
b=(1,)
c={"name":"Andy"}
print(type(a),type(b),type(c)) #
print(isinstance(a,Iterable),isinstance(b,Iterable),isinstance(c,Iterable)) #True True True
print(isinstance(a,Iterator),isinstance(b,Iterator),isinstance(c,Iterator)) #False False False
a_iterator=iter(a)
b_iterator=iter(b)
c_iterator=iter(c)
print(isinstance(a_iterator,Iterable),isinstance(b_iterator,Iterable),isinstance(c_iterator,Iterable)) #True True True
前面我讲过 getitem 这个魔法函数,它可以改变对象类型变成一个iterable ,也就是迭代器
例如:
class Person:
def __init__(self,persion_list):
self.persion_list=persion_list
def __getitem__(self, item):
return self.persion_list[item]
body=Person(["Xiuwu","Adny","Maggie"])
for i in body:
print (i)
上边的代码我们用for循环的时候, 实际上就用了iter()方法 ,不理解可以看看我的上篇写作.
然后看下如下代码
class Person:
def __init__(self, persion_list):
self.persion_list = persion_list
def __iter__(self):
return 1
def __getitem__(self, item):
return self.persion_list[item]
body = Person(["Xiuwu", "Adny", "Maggie"])
body=iter(body)
打印结果:
iter() returned non-iterator of type 'int'
1.说明 用iter(body)的时候首先找到 ——iter__方法,由于我们返回的不是的个iterator所以报错,
2. __iter__方法找不到,它会继续找 是否有模拟返回迭代器呢,
3. 如果你把__iter__注销掉,它会找到——getitem——
咱们测试下,是否getitem 是否实现iterable ,代码如下:
from collections import Iterable, Iterator
class Person:
def __init__(self, persion_list):
self.persion_list = persion_list
#def __iter__(self):
# return 1
def __getitem__(self, item):
return self.persion_list[item]
body = Person(["Xiuwu", "Adny", "Maggie"])
print(iter(body)) #
print(isinstance(iter(body),Iterator) #True 说明getitem是可以转化为iterable
如果把getitem 也注销,按道理应该body 不是iterable了,试试
注销之后再运行报错如下:
TypeError: 'Person' object is not iterable
证明咱们的想法是对的.
3.分析原理后,咱们就自己写个迭代器.
前面我们已经知道了,迭代器需要重写两个方法,如下:
class Myiterator:
def __iter__(self):
pass
def __next__(self):
pass
如果继承了 Iterator类 ,iter 方法 可以删除.如下:
class Myiterator(Iterator):
def __next__(self):
pass
这个__next__ 正是我们要重写的取值逻辑
完成的代码如下,解释请看备注:
from collections import Iterable, Iterator
class Person:
def __init__(self, persion_list):
self.persion_list = persion_list
def __iter__(self):
return Myiterator(self.persion_list) #调用我们重写的迭代器方法
#def __iter__(self):
# return 1
#def __getitem__(self, item): #把这个方法用我们自己写的迭代器方法替代.
# return self.persion_list[item]
class Myiterator(Iterator): #继承Iterator 就不需要写__iter__,直接调用父类的.
def __init__(self,persion_list):
self.persion_list=persion_list
self.index=0 #由于iterator 是没有index 的,这个要我们手动添加
def __next__(self): #这个就是迭代器的取值逻辑
while True: #当为false 的时候结束循环
try:
word = self.persion_list[self.index] #取值动作
except IndexError: #index 当变得超出persion_list 会报错的 ,先抓住这个异常
raise StopIteration #迭代到没有值要用这异常,咱们把异常做个转化
self.index = self.index + 1 #递增我们的index
return word #返回取到的值
body = Person(["Xiuwu", "Adny", "Maggie"])
a=iter(body) #调用我们自定义的迭代器方法
print(a) # <__main__.Myiterator object at 0x00000000022399B0>
#从打印结果看说明我们自定义的迭代器方法生效了,已经返回一个迭代器
print(next(a)) #Xiuwu
#从打印结果我们判断出 __next__生效,如果想循环输出,自己试试for 循环.