迭代器可以使用next()函数依次获取该迭代器内的下一个值,迭代器可以使程序更通用、优雅、高效、更具有Python编码风格。普通对象可以通过实现__iter__()与__next__()两个方法,使得对象变为可迭代对象,可以通过循环进行迭代。如果类只实现了__iter__()方法,该类生成的对象就变为了可迭代对象,只不过运行的时候会报TypeError: iter() returned non-iterator of type '**'如果只实现__next__()方法那么程序会报TypeError: '**' object is not iterable所以只有将类的两个方法都实现了,对象才会变为能够迭代的对象。__iter__()与__next__()方法又称为迭代器协议。
💓实现方式
将两方法实现一下,然后方法iter中返回对象本身,next返回你要返回的下一个值。
测试可迭代对象是否可迭代
import collections.abc
classITClass:def__init__(self,name):
self.__name=name
self.a=1# 以下二者合称为迭代器协议def__iter1__(self):return self
def__next__(self):
self.a+=1return self.a
i1=ITClass("小黄")# 测试对象是否可迭代print(isinstance(i1,collections.abc.Iterable))print(isinstance(ITClass,collections.abc.Iterable))print(isinstance([1,2,3],collections.abc.Iterable))# 测试对象是不是迭代器print(isinstance(i1,collections.abc.Iterator))print(isinstance(ITClass,collections.abc.Iterator))print(isinstance((i for i inrange(100)),collections.abc.Iterator))# 只有i1对象的isinstance的两项结果都为True的时候才可以无限循环迭代。for i in i1:print("Hello")
使用迭代器实现斐波那契数列
classfib:def__init__(self,nums):
self.nums=nums
self.a,self.b=0,1
self.i=0def__iter__(self):return self
def__next__(self):
self.i+=1# 达到终止条件就抛出异常来终止否则会一直迭代下去if self.i>self.nums:raise StopIteration
self.a,self.b=self.a+self.b,self.a
return self.a
f=fib(100)for i in f:print(i)
classRange:def__init__(self,startnums,endnums):
self.endi=endnums
self.a,self.b=0,1
self.starti=startnums
def__iter__(self):while self.starti<=self.endi:yield self.starti
self.starti+=1def__reversed__(self):while self.starti<=self.endi:yield self.endi
self.endi-=1
f1=Range(10,20)for i in f1:print(i)
f2=reversed(Range(10,20))for i in f2:print(i)
💓手写一个range函数
可以传入起始数值、结尾数值。默认步长是1,也可以自己传入,支持正反向迭代。
classRange:def__init__(self,startnums,endnums,dis=1):
self.endi=endnums
self.starti=startnums
self.dis=dis
def__iter__(self):
i=self.starti
j=self.endi
if self.starti<self.endi:while i<=self.endi:yield i
i+=self.dis
else:while self.endi<=i:yield i
i-=self.dis
f1=Range(10,30,2)for i in f1:print(i)
defgentripls(n):for i inrange(n):yield i*3
f=gentripls(10)for i in f:print(i)# 生成器表达式# 生成器表达式与列表推导式基本一样,只不过使用()代替了[]
ls=(1,2,3,4,5,6)for i in ls:print(i)