czsay 2020-06-01
? ? 可循环迭代的对象称为可迭代对象,迭代器和生成器函数是可迭代对象,在Python中提供了定义迭代器和生成器的协议和方法。
1.可迭代对象
? ? 在Python中,实现了__iter__()的对象是可迭代对象(Iterable)。使用内置函数iter(obj),可以调用可迭代对象obj的__iter__()方法,并返回一个迭代器(iterator)。如字符串、元组、列表等都是可迭代对象,生成器函数和生成器表达式也是可迭代对象。判断一个对象是否为可迭代对象,可使用以下方式:
>>> from collections import abc >>> isinstance((1,2,3,4),(abc.Iterable,)) True >>> isinstance("abcdef",(abc.Iterable,)) True >>> isinstance(123,(abc.Iterable,)) False >>> isinstance("123",(abc.Iterable,)) True >>> isinstance({1,2,3},(abc.Iterable,)) True >>> isinstance({"a":1,"b":2},(abc.Iterable,)) True
2.迭代器
? ? 实现了__next__的对象是迭代器,可以使用内置函数next(),调用迭代器的__next__()方法,依次返回下一个值,如果没有值,则抛出异常StopIteration。使用迭代器可以实现对象的迭代循环,让程序更加通用,高效。示例如下所示:
>>> from collections import abc >>> tempA=(i**2 for i in range(10)) >>> isinstance(tempA,(abc.Iterable,)) True >>> tempB={i*2 for i in range(10)} >>> isinstance(tempB,(abc.Iterable,)) True
3.迭代器协议
? ? 迭代器对象必须实现两个方法__iter__()和__next__(),这两个方法被称为迭代器协议。__iter__()用于返回对象本身,以方便使用循环语句(for)进行迭代,__next__()用于返回下一元素。示例如下所示:
>>> from collections import abc >>> tempA=(i**2 for i in range(10)) >>> help(tempA) | __iter__(self, /) | Implement iter(self). | | __next__(self, /) | Implement next(self).
? ? 使用内置函数iter(iterable),可以返回可迭代对象iterable的迭代器;使用内置函数next()函数,可依次返回迭代器对象的下一个值,如果没有值,则抛出异常StopIteration。示例如下所示:
>>> temp=[1,2,3,4] # 可迭代对象 >>> v=iter(temp) # 通过内置函数iter获取iterator >>> next(v) # 通过内置函数next获取值 1 >>> next(v) 2 >>> next(v) 3 >>> next(v) 4 >>> next(v) # 当没有值,则抛出异常StopIteration Traceback (most recent call last): File "<input>", line 1, in <module> StopIteration
? ? 除了使用next函数个,也可以使用while循环可迭代对象,如下所示:
temp=[1,2,3,4] v=iter(temp) while True: try: value=next(v) except StopIteration: break print(value,end=" ")
运行结果如下所示:
1 2 3 4
? ? 实际项目中,通常会使用for语句实现可迭代对象的迭代。Python中的for循环实现了自动迭代可迭代对象的功能,如下所示:
>>> temp=[1,2,3,4] >>> for item in temp: ... print(item,end=" ") ... 1 2 3 4 >>> for item in "abcdef": ... print(item,end="-") ... a-b-c-d-e-f-
? ? 创建一个类,定义__iter__()和__next__()两个方法。实例化该类的对象,即为可迭代对象,也是迭代器。示例如下所示:
class Fibonacci: def __init__(self): self._first=0 self._second=1 def __next__(self): # f(n)=f(n-1)+f(n-2) self._first,self._second=self._second,self._first+self._second return self._first def __iter__(self): return self fib=Fibonacci() for f in fib: if f<100: print(f,end=" ") else: break
输出结果如下所示:
1 1 2 3 5 8 13 21 34 55 89
? ? 在函数定义中,如果使用关键字yield语句代替return返回一个值,则表示定义了一个生成器函数(generator)。生成器函数使用yield语句返回一个值,然后保存当前函数的整个执行状态,等待下一次调用。生成器函数是一个迭代器,是可迭代对象。示例如下所示:
>>> def generatorSample(n): ... for i in range(n): ... yield i**2 ... >>> f=generatorSample(5) >>> f <generator object generatorSample at 0x00000260CE70E7C8> >>> item=iter(f) # 通过内置函数iter获得iterator >>> next(item) # 通过内置函数next获取一个值 0 >>> next(item) # 通过内置函数next获取一个值 1 >>> for i in f: ... print(i,end=" ") ... 4 9 16 # 使用for循环获取剩下的值
? ? 下面我们再用生成器生成Fibonacci数列,示例代码如下所示:
def Fibonacci(): first,second=0,1 while True: first,second=second,first+second yield first for f in Fibonacci(): if f<100: print(f,end=" ") else: break
输出结果如下所示:
1 1 2 3 5 8 13 21 34 55 89
? ? 使用内置函数reversed(),可以实现一个反向迭代器。如果一个可迭代对象实现了__reversed__()方法,则可使用reversed()函数获得其反向可迭代对象。示例如下所示:
>>> reversed([1,2,3,4,5]) <list_reverseiterator object at 0x00000260CF0D8908> >>> for item in reversed([1,2,3,4,5]): ... print(item,end=" ") ... 5 4 3 2 1
? ? 实现一个可反向迭代的迭代器示例:
class CountSample: def __init__(self,startIndex): self._startIndex=startIndex # 正向迭代 def __iter__(self): n=self._startIndex while n > 0: yield n n-=1 # 反向迭代 def __reversed__(self): n=1 while n<= self._startIndex: yield n n+=1 if __name__ == ‘__main__‘: obj=CountSample(10) print("正向迭代") for item in obj : print(item,end=" ") print("\n反向迭代") for item in reversed(obj): print(item,end=" ")
输出结果如下所示:
正向迭代 10 9 8 7 6 5 4 3 2 1 反向迭代 1 2 3 4 5 6 7 8 9 10
? ? 使用生成器表达式,可以简便快捷返回一个生成器。生成器表达式的语法和前面所讲的列表解析式基本一样,区别在于生成器表达式使用()代表[],基本使用格式如下所示:
( expr for iterVar in iterable ) ( expr for iterVar in iterable if condition)
? ? 表达式expr使用每次迭代内容iterVar,计算生成一个列表。如果在指定条件表达式condition,则只有满足条件的iterable元素参与迭代。如下所示:
>>> (i**2 for i in range(10)) <generator object <genexpr> at 0x00000260CF0B0EC8> # 输出表明是一个生成器 >>> for item in (i**2 for i in range(10)): ... print(item,end=" ") ... 0 1 4 9 16 25 36 49 64 81 >>> for item in (i**2 for i in range(10) if i%2==0): ... print(item,end=" ") 0 4 16 36 64
本文地址:https://www.cnblogs.com/surpassme/p/13028211.html
本文同步在微信订阅号上发布,如各位小伙伴们喜欢我的文章,也可以关注我的微信订阅号:woaitest,或扫描下面的二维码添加关注: