def my_generator(): print(1111) yield '结果1' print(2222) yield '结果2' print(3333) yield '结果3' print(4444) yield '结果4' g_obj = my_generator() # my_generator()并不会执行函数体,得到的返回值就是生成器对象,生成器对象就是迭代器对象 r1 = g_obj.__next__() print(r1) # 在函数内部执行一次,在遇到下一个yield时停止,且可以拿到yield的返回值 r2 = g_obj.__next__() print(r2) # 从上一次停止的位置紧着往下走,在再遇到下一个yield时停止,且可以拿到yield的返回值 # 生成器可以被for循环迭代 for v in g_obj: print(v)
一、迭代器概念
1、迭代器:从装有多个值的容器中一次取出一个值给外界
ls = [100, 200, 300, 400, 500] # 被遍历的对象必须是有序容器 i = 0 while i < len(ls): print(ls[i]) i += 1 通过迭代器取值优缺点: 优点:不依赖索引完成取值 缺点:不能计算长度,不能指定位置取值(只能从前往后逐一取值)
2、可迭代对象:该对象有__iter__方法
有哪些:str、list、tuple、dict、set、range()、file、迭代器对象、enmerate()、生成器
[].__iter__()().__iter__(){}.__iter__(){}1,}.__iter__() 可迭代对象通过__iter__方法得到迭代器对象
3、迭代器对象:有__next__方法
通过该方法获得容器中的值,获取规则,从前往后,一次一个。
迭代器对象可以做到不依赖索引取值(一次从容器中取出一个值)
有哪些:file、ensumerate()、生成器
从迭代器对象中取元素,取一个少一个,如果要从头开始取,需要重新获得拥有所有元素的迭代器对象
迭代器对象也有__iter__()方法,调用后得到的是自己本身(当前含有几个元素,得到的就只有几个元素的迭代器对象)
# 可迭代对象 ls = [1,2,3,4,5] # 迭代器对象 iter_obj = ls.__iter__() print(iter_obj) # <list_iterator object at 0x00000000021E75C0> print([1,2,3,4,5].__iter__()) # 结果为 <list_iterator object at 0x0000000002207780> # 迭代器对象取一个值就少一个值 ls = [100, 200, 300, 400, 500] iter_obj = ls.__iter__() print(iter_obj.__next__()) # 100 print(iter_obj.__next__()) # 200 print(iter_obj.__next__()) # 300 print(iter_obj.__next__()) # 400 print(iter_obj.__next__()) # 500 # print(iter_obj.__next__()) # 值取完了就抛异常StopIteration,可以通过try对异常捕获并处理 # 上一个迭代器对象迭代取值完毕后,就取空了,如果要再次取值,要重新生成迭代器对象 # iter_obj =ls.__iter__()
# 迭代器对象不能求长度(内部值的个数) ls = [100,200,300,400,500] iter_obj = ls.__iter__() while True: try: ele = iter_obj.__next__() print(ele) except StopIteration: print('取完了') break
4、for循环迭代器
自带异常处理的while循环,自动获取被迭代对象的迭代器对象
ls = [100,200,300,400,500] iter_obj = ls.__iter__() for ele in iter_obj: print(ele) for ele in ls: # 1.自动完成 for ele in st1.__iter__(): 2.自动完成异常处理 print(ele)
5、总结
①可迭代对象:有__iter__()方法的对象,采用该方法可以得到迭代器对象
②迭代器对象:有__next__()方法的对象,用该方法可以从可迭代对象中一次获取一个值,取出一个少一个
③for循环迭代器:
自动获取被迭代对象的迭代器对象
在内部一次次调用__next__()方法取值
自动完成异常处理
obj = [100, 200, 300].__iter__()
for v in obj:
print(v)
if v == 200:
break
# 结果为100200
obj = [100, 200, 300].__iter__()
print(obj.__iter__().__iter__().__iter__() is obj) # True可迭代对象.__iter__()得到的是该对象的迭代器对象迭代器对象.__iter__().__iter__()得到的就是迭代器对象本身
二、生成器
1、生成器:就是一个迭代器对象
包含yield关键字的函数就是生成器
该函数名()得到的是生成器对象,不会执行函数体
def fn(): print('我是生成器') yield 'god' generator_obj = fn() print(generator_obj) # 结果为 <generator object fn at 0x0000000001DF0EB8> print(type(generator_obj)) # 结果为 <class 'generator'> generator_obj.__iter__() # 可迭代对象 generator_obj.__next__() # 迭代器对象
2、生成器的应用案例:
当访问的数据资源过大,可以将数据用生成器处理,一次只获取所有内容的一条资源
def my_range(min,max=0,step=1): tag = min while True: if tag >= max: break yield tag tag += step range_obj = my_range(5, 10,1 ) for i in range_obj: print(i)
三、枚举对象
通过for迭代器,循环遍历可迭代对象,需要知道迭代的索引
ls = [100, 200, 300, 400, 500] count = 0 for v in ls: print(count,v) count +=1 # 结果为0 1001 2002 3003 4004 500 ls = [100,200,300,400,500] for count, v in enumerate(ls): print(count, v) # 结果为0 1001 2002 3003 4004 500