迭代器与生成器:
一、迭代器协议:
对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIteration异常,以终止迭代(只能往后走不能往前退)
2、可迭代对象:实现了迭代器协议的对象(对象内部定义了__iter__())
3、协议是一种约定,可迭代对象实现了迭代器协议,python内部工具(for循环,sum,min,max函数等)使用迭代器协议访问对象。
强大的for循环机制:字符串,列表,元组,字典,集合,文件都不是可迭代对象,只不过for循环式,调用了他们内部的__iter__()方法,把他们变成了可迭代对象。
1 l=[1,2,3] 2 iter_l=l.__iter__()#遵循迭代器协议,生产可迭代对象 3 print(iter_l.__next__()) 4 print(iter_l.__next__()) 5 print(iter_l.__next__())
# 1
# 2
# 3
for循环基于迭代器协议工作。先调用对象的__iter__方法,将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象都可以通过for循环遍历。
使用while循环遍历列表(字符串,元组)
1 l=[1,2,3] 2 index=0 3 while index < len(l): 4 print(l[index]) 5 index+=1
输出结果同上
使用迭代器遍历集合:
1 s={1,2,3} 2 iter_s=s.__iter__() 3 print(iter_s) 4 print(iter_s.__next__()) 5 print(iter_s.__next__()) 6 print(iter_s.__next__()) 7 # <set_iterator object at 0x01A23120> 8 # 1 9 # 2 10 # 3
使用迭代器遍历字典:
1 dic={'name':"alex",'age':18} 2 iter_dic=dic.__iter__() 3 print(iter_dic) 4 print(iter_dic.__next__()) 5 print(iter_dic.__next__()) 6 # <dict_keyiterator object at 0x028F7ED0> 7 # age 8 # name
使用迭代器遍历文件
1 f=open('爱情悬崖','r+',encoding='utf-8') 2 iter_f=f.__iter__() 3 print(iter_f) 4 print(iter_f.__next__()) 5 print(iter_f.__next__()) 6 print(iter_f.__next__()) 7 # <_io.TextIOWrapper name='爱情悬崖' mode='r+' encoding='utf-8'> 8 # 你说我像一个小孩 9 # 10 # 总爱让你猜 11 # 12 # 我说你才像个小孩
注意:上述代码中,iter_f.__next__()等同于next(iter_f)
next方法:就是在调用iter_f.__next__()方法
迭代器就是可迭代对象
二、生成器:
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己的内置__iter__()方法),因此生成器就是可迭代对象。
生成器在python中的表现形式:
1、生成器函数:常规函数定义,但是使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,而没个结果中间,挂起函数的状态,以便下次从他离开的地方执行。
2、生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表。
列表for循环遍历生成:
l=[i for i in range(10)] print(l) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
生成器生成:
1 g_l=(i for i in range(10)) 2 print(g_l) 3 print(g_l.__next__()) 4 print(g_l.__next__()) 5 print(g_l.__next__()) 6 # <generator object <genexpr> at 0x0268E1C0> 7 # 0 8 # 1 9 # 2
生成器函数形式:
1 def test(): 2 yield 1 3 yield 2 4 yield 3 5 res=test() 6 print(res)#------生成对象 7 print(res.__next__()) 8 print(res.__next__()) 9 print(res.__next__()) 10 # print(res.__next__()) #StopIteration 11 # <generator object test at 0x024BE148> 12 # 1 13 # 2 14 # 3
使用for循环遍历与生成器遍历的区别:
1 def product_l(): 2 ret=[] 3 for i in range(10): 4 ret.append('剑%s' %i) 5 return ret 6 jian_l=product_l() 7 print(jian_l) 8 #['剑0', '剑1', '剑2', '剑3', '剑4', '剑5', '剑6', '剑7', '剑8', '剑9']
生成器:
def product_l(): for i in range(100): yield '剑%s' %i pro_g=product_l() jianke=pro_g.__next__() jianke=pro_g.__next__() jianke=pro_g.__next__() print(jianke) #剑2
yield可以保持函数运行状态,节省内存,效率高。
生成器函数总结:
1、语法上和函数类似:生成器函数和常规函数几乎一样。它们都是使用def语句进行定义。差别在于,生成器函数使用yield语句返回一个值,而常规函数使用return语句返回一个值。
2、自动实现迭代器协议:对于生成器,python会自动实现迭代器协议。以便应用到迭代背景中(如for循环,sum函数)。由于生成器实现了迭代器协议。所以,我们可以调用next方法。并且,在没有值可以返回时,生成器自动产生StopIteration异常。
3、状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态。保留足够的信息,以便之后从它离开的地方继续执行。
优点:
1、生成器的好处是延迟计算,一次返回一个结果。他不会一次生成所有结果,这有利于大量数据处理。
2、生成器还能有效提高代码可读性。
示例:
1 def test(): 2 for i in range(4): 3 yield i 4 t=test() 5 6 for i in t: 7 print(i) 8 t1=(i for i in t)#for循环遍历生成器------------>生成器 9 print(list(t1)) #生成器只能遍历一次,相当于将列表中的元素不可逆的按照顺序取出。 10 # 0 11 # 1 12 # 2 13 # 3 14 # [] 15 t1=(i for i in t) 16 t2=(i for i in t1) 17 print(list(t1)) 18 print(list(t2)) 19 # [0, 1, 2, 3] 20 # []
三、三元运算:
1 # 书写格式 2 3 result = 值1 if 条件 else 值2 4 5 # 如果条件成立,那么将 “值1” 赋值给result变量,否则,将“值2”赋值给result变量
1 name='alex' 2 name='linhaifeng' 3 res='SB' if name =='alex' else 'shuai' 4 print(res)
#shaui