迭代器和生成器

 阅读目录

楔子

假如有列表 lst = [1,2,3,4],如果想获取列表中的内容,我们有几种方式?

第一种,可以用索引取值;

第二种,可以用for循环,但是也存在特殊情况,比如整型不能用来for循环取值,举个例子:

for i in 123:
    print(i)

结果:

TypeError: 'int' object is not iterable
'int' object is not iterable 意思是: 整型是不可迭代的

那么,什么是可迭代的呢?
lst = [1,2]
print(dir(lst))
结果:
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__',
'__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
from collections import Iterable
                             
l = [1,2,3,4]                
t = (1,2,3,4)                
d = {1:2,3:4}                
s = {1,2,3,4}                
                             
print(isinstance(l,Iterable))
print(isinstance(t,Iterable))
print(isinstance(d,Iterable))
print(isinstance(s,Iterable))
结果:
True
True
True
True

结合上述代码,我们可以得出可迭代协议。可迭代协议简单来说,就是内部实现了__iter__方法.

也就是说,要想可迭代,内部必须要有__iter__方法,那么,__iter__做了什么呢?

print([1,2].__iter__())
结果:
<list_iterator object at 0x00000000027B7198> 

iterator

迭代器

我们又得到了一个新的词语--迭代器。那么,什么是迭代器呢?先来看段代码:

l = [1,2,3,4]
res = l.__iter__()
print(res)
结果:
<list_iterator object at 0x00000000024115F8> #iterator 迭代器

再用dir()查看l和res可实现的方法:
print(dir(l))
print(dir(res))

结果:

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']

再来看在res中,但不在l中的方法:

print(set(dir(res))-set(dir(l)))

结果:

{'__next__', '__length_hint__', '__setstate__'}  #这些就是迭代器中特有的方法。

我们再来看看迭代器中特有的三种方法的功能。

print(res.__length_hint__()) # 迭代器中有多少个元素

结果: 4

res.__setstate__(2) # 控制迭代器从哪儿开始迭代

for i in res:

  print(i)

结果:

3
4

print(res.__next__()) # 从迭代器中取下一个值

print(res.__next__())

print(res.__next__())

print(res.__next__())

结果:

1
2
3
4

 那么,迭代器方法中能够实现一个一个取值的是什么?就是__next__

for循环,就是在内部调用了__next__从而实现了一个一个取值.

所以,迭代器遵循迭代协议:必须拥有__iter__和__next__方法

迭代器的特点:

1,具有iter和next方法;

2,通过多次执行next就可以获得迭代器中的所有的值;

3,迭代器中的值只能取一次

4,不取的时候值不出现

迭代器的优点就是:节省内存

 关于迭代器的分析就到这里了,最后,我们再来分析一下,range()是不是一个迭代器呢?

print('__iter__' in dir(range(5)))
print('__next__' in dir(range(5)))
print('__next__' in dir(range(5).__iter__()))
from collections import Iterator 
print(isinstance(range(5),Iterator))

结果:
True
False
True
False

生成器

Python中提供的生成器:

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

生成器函数

 所谓的生成器函数,就是包含了yield关键字的函数。

那么,生成器有什么好处呢?就是不会一下子在内存中生成太多数据。

假如我想让工厂给学生做校服,生产2000000件衣服,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一件一件的要,也可以根据学生一批一批的找工厂拿。
而不能是一说要生产2000000件衣服,工厂就先去做生产2000000件衣服,等回来做好了,学生都毕业了。。。

def produce():
    """生产衣服"""
    for i in range(2000000):
        yield "生产了第%s件衣服"%i

product_g = produce()
print(product_g.__next__()) #要一件衣服
print(product_g.__next__()) #再要一件衣服
print(product_g.__next__()) #再要一件衣服
num = 0
for i in product_g:         #要一批衣服,比如5件
    print(i)
    num +=1
    if num == 5:
        break

 

 

 

 

原文地址:https://www.cnblogs.com/yaraning/p/9909196.html