python 迭代器和生成器
一、什么是迭代器协议
1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个stoplteration异常,以终止迭代(只能 往后走,不能往前退)
2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象
可迭代对象
可迭代对象泛指一类对象,不是指的每一种对象,确切的说满足以下的条件的对象可以成为可迭代对象:
1. 对象实现了__iter__方法
2. __iter__方法返回了一个迭代器对象
我们比较容易理解的可迭代对象,比如说可以用for语句去遍历,实际for语句的内部实现应该就是首先调用对象的__iter__方法,获取一个迭代器对象,接着不停的调用迭代器对象的__next__方法,循环遍历取值。
迭代器对象(迭代器)
迭代器协议包括这些条件:
1.对象实现了__next__方法
2.__next__方法返回了某个数值(当然一般情况下,我们需要的是返回这个对象的特定的数字,并且按照一定的顺序进行依次返回)
3.__next__方法需要在值取完的时候,抛出StopIteration的错误信息。
总结:
可迭代对象是 调用对象的__iter__方法能够返回迭代器对象的一种对象。
迭代器对象是实现了迭代器协议的对象。
迭代器有两个基本的方法:iter() 和 next()
列表,元组,集合,字典,字符串都可用于创建迭代器:
l=[1,2,3,4] t=(1,2,3,4) set={1,2,3,4} d={'name':'zs','age':20} s='abcdef' i=123 l1=l.__iter__() t1=t.__iter__() set1=set.__iter__() d1=d.__iter__() s1=s.__iter__() print(type(l.__iter__())) print(type(t.__iter__())) print(type(set.__iter__())) print(type(d.__iter__())) print(type(s.__iter__()))
只有可迭代对象才可以使用__iter__()方法,非 iterable 对象不能调用这个方法哦,比如整型,可以直接用 for 循环的对象都叫可迭代对象,
迭代器的访问
两种方式,一种是直接next访问,一种是for访问
#for迭代和next()迭代两种方式完全一样 for x in l1: print(x) print("####################################################") #for迭代已经完成,下面的next()迭代不会再有任何输出,反过来也是一样 while True: try: print (next(l1)) except StopIteration: pass
创建一个迭代器
把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__()
class MyNumbers:
#__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。 def __iter__(self): self.a = 1 return self #__next__() 方法会返回下一个迭代器对象。 def __next__(self): if self.a <= 20: x = self.a self.a += 1 return x else:
#StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况 raise StopIteration myclass = MyNumbers() myiter = iter(myclass) for x in myiter: print(x)
生成器
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己的内置的__iter__方法),所以生成器就是可迭代对象
使用了yield关键字的函数就是生成器,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
def test(): yield 1 yield 2 t=test() for i in t: print(i)
- yield有点像断点。 加了yield的函数,每次执行到有yield的时候,会返回yield后面的值 并且函数会暂停,直到下次调用或迭代终止;
- yield后面可以加多个数值(可以是任意类型),但返回的值是元组类型的。
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
为何使用生成器之生成器的特点
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。
生成器小结:
a.是可迭代对象
b.实现了延迟计算,省内存
c.生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处
生成器使用的简单例子
def myegg(retlist): for i in retlist: rec = yield i mydict = [ {"name":"厉智","age":31}, {"name":"陈培昌","age":21}, {"name": "程劲", "age": 20}, ] b = myegg(mydict) obj = b.__next__() print("喜欢{},芳龄{}".format(obj['name'],obj['age'])) obj2 = b.__next__() print("喜欢{},芳龄{}".format(obj2['name'],obj2['age'])) obj3 = b.__next__() print("喜欢{},芳龄{}".format(obj3['name'],obj3['age']))
作者:huxt
链接:https://www.jianshu.com/p/dcc4c1af63c7
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。