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)
  1. yield有点像断点。     加了yield的函数,每次执行到有yield的时候,会返回yield后面的值 并且函数会暂停,直到下次调用或迭代终止;
  2. 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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted on 2021-07-26 22:12  铭烟  阅读(74)  评论(0编辑  收藏  举报