迭代器 与 生成器
#############迭代器与生成器################
-可迭代对象与迭代器
- 可迭代对象:像str,list,tuple,set,dict这样的数据类型,range
- 如何检测是否为可迭代对象:看功能中是否包含‘双下iter’ __iter__,如果含有就是可迭代对象
- 可迭代协议:数据类型和python解释器定下来的协议,只要包含了“双下iter”方法的数据类型就是可迭代的 —— 可迭代协议
#方法一 print(dir('aaa')) #其中包含 __iter__ 方法的就是可迭代对象 #方法二 from collections import Iterable #检测一个对象是否可迭代 print(isinstance('aaa',Iterable)) #True print(isinstance(123,Iterable)) #False
- 迭代器:可迭代对象.__iter__() 就是迭代器,作用就是一个一个的从其中向外拿值
- 如何检测是否是迭代器:看功能中是否包含 __iter__和__next__这两个功能,如果含有就是迭代器
- 迭代器协议:迭代器中有 __next__ 和 __iter__方法 —— 迭代器协议
lst_iterator = [1,2,3].__iter__() from collections import Iterator print(isinstance(lst_iterator,Iterator)) #True print(isinstance([1,2,3],Iterator)) #False
- 迭代器的方法: __next__ , 当迭代器中没有值往外拿是,继续__next__方法就会报错
#把迭代器赋值给一个变量,再操作变量进行.__next__()功能
lst_iterator = [1,2,3].__iter__() print(lst_iterator.__next__()) #1 print(lst_iterator.__next__()) #2 print(lst_iterator.__next__()) #3 #直接操作迭代器.__next__()功能 lst_iterator = [1,2,3].__iter__() print([1,2,3].__iter__().__next__()) #1 print([1,2,3].__iter__().__next__()) #1 print([1,2,3].__iter__().__next__()) #1
可以把[1,2,3].__iter__()看成一个函数,如果直接使用不赋值给变量,则每次都要重新调用函数
- 迭代器:有天生是迭代器,比如文件句柄 ; 有后天改造成的,可迭代对象.__iter__()
- for循环 可以循环可迭代对象,也可以循环迭代器
- 循环可迭代对象 每一个for循环都会从新开始
t=[1,2,3] for i in t: print(i) 123 for i in t: print(i) 123
- 循环迭代器 若第一个for循环完,下一个for循环将不会循环到值
t=[1,2,3].__iter__() for i in t: print(i) 123 for i in t: print(i)
- for 循环的意义:
- 1.能够对python中的基本数据类型进行统一的遍历,不需要关心每一个值分别是什么
- 2.它可以节省内存 —— 惰性运算
- 生成器 : 生成器就是迭代器 只是生成器是自己写成的迭代器
- 生成器函数:常规函数定义,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
-形式:一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
def generator_func(): #生成器函数 print(123) yield 'aaa' print(456) yield 'bbb' g = generator_func() ret = g.__next__() # 123 print(ret) # 'aaa' ret = g.__next__() # 456 print(ret) # 'bbb'
- 生成器与list(),tuple()
def generator_func(): yield 'aaa' yield 'bbb' g = generator_func() print(list(g)) #['aaa', 'bbb']
- 生成器与for循环
def generator_func(): #生成器函数 yield 'aaa' yield 'bbb' g = generator_func() for i in g: print('i : ',i) #i:aaa #i:bbb
def get_clothing(): for cloth in range(1,200): yield '第%s件衣服'%cloth generate = get_clothing() print(generate.__next__()) # 1 print(generate.__next__()) # 2 print(generate.__next__()) # 3 for i in generate: print(i) # 4-199 ########## def get_clothing(): for cloth in range(1,200): yield '第%s件衣服'%cloth generate = get_clothing() for i in range(9): print(generate.__next__()) # 1-9 for i in get_clothing(): print(i) # 1-101 if i == '第101件衣服': break
- 生成器的注意事项:
- 带yield关键字的函数就是生成器函数
- 生成器函数在执行的时候只返回一个生成器,不执行生成器函数中的内容
- 从生成器中取值
- __next__ 有几个yield就可以取几次
- for循环取值 正常取
- 其他数据类型进行强制转换 list(g) 返回一个列表,里面装着生成器中的所有内容
-注意:调用生成器函数的时候,要先获取生成器,再进行next取值
生成器中的内容只能取一次,且按顺序取值没有回头路,取完为止。
- yield from
def func(): for i in [1,2,3]: yield i for j in 'ABC': yield j g=func() for i in g: print(i) 1,2,3,A,B,C
def func2(): yield from [1,2,3] yield from 'q' g = func2() for i in func2(): print(i) 1,2,3,q