Python全栈之推导式和生成器
目录
- 1. 推导式
- 2. 推导式练习
- 3. 集合_字典推导式
- 4. 生成器
- 4.1 生成器表达式
- 4.2 生成器函数
- 5. 小练习
- 总结
1. 推导式
# ### 推导式 : 通过一行循环判断遍历出一些列数据的方法叫做推导式 """ 语法: val for val in iterable """ # 1.推导式基本语法 lst = [] for i in range(1,51): lst.append(i) print(lst) # 改写推导式 lst = [ i for i in range(1,51) ] print(lst) # 小练习 # 1.[1,2,3,4,5] => [2,4,6,8,10] lst = [ i*2 for i in range(1,6) ] print(lst) # 2.带有判断条件的推导式 """注意点:for后面紧跟的判断条件只能是单项分支.""" """[1,2,3,4,5,6,7,8,9,10] => [1,3,5,7,9 ... ]""" lst = [1,2,3,4,5,6,7,8,9,10] lst_new = [] for i in lst: if i % 2 == 1: lst_new.append(i) print(lst_new) # 改写推导式 lst = [ i for i in lst if i % 2 == 1 ] print(lst) # 3.多循环推导式 # 谁♡♢♤♠谁 lst1 = ["孙杰龙","陈露","曹静怡"] lst2 = ["王志国","邓鹏","合理"] lst_new = [] for i in lst1: for j in lst2: lst_new.append(i+"♡♢♤♠"+j) print(lst_new) # 改写推导式 www.cppcns.comlst = [ i+"♡♢♤♠"+j for i in lst1 for j in lst2 ] print(lst) # 4.带有判断条件的多循环推导式 lst_new = [] for i in lst1: for j in lst2: if lst1.index(i) == lst2.index(j): lst_new.append(i+"♡♢♤♠"+j) print(lst_new) # 改写推导式 lst = [i+"♡♢♤♠"+j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j)] print(lst)
2. 推导式练习
# ### 推导式练习题 # (1).{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式 dic = {'x': 'A', 'y': 'B', 'z': 'C' } lst = [] for k,v in dic.items(): res = k + "=" + v lst.append(res) print(lst) # 推导式 lst = [ k + "=" + v for k,v in dic.items() ] print(lst) # (2).把列表中所有字符变成小写 ["ADDD","dddDD","DDaa","sss"] lst = ["ADDD","dddDD","DDaa","sss"] lst_new = [] for i in lst: lst_new.append(i.lower()) print(lst_new) # 推导式 lst = [ i.lower() for i in lst ] print(lst) # (3).x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中 # 方法一 lst = [] for x in range(6): for y in range(6): if x % 2 == 0 and y % 2 == 1: lst.append( (x,y) ) print(lst) # 推导式 lst = [ (x,y) for x in range(6) for y in range(6) if x % 2 == 0 and y % 2 == 1 ] print(lst) # 方法二 lst = [] for x in range(6): if x % 2 == 0 : for y in range(6): if y % 2 == 1: lst.append( (x,y) ) print(lst) # 推导式 lst = [ (x,y) for x in range(6) if x % 2 == 0 for y in range(6) if y % 2 == 1 ] print(lst) # (4).使用列表推导式 制作所有99乘法表中的运算 for i in range(1,10): for j in range(1,i+1): print("{:d}*{:d}={:2d} ".format(i,j,i*j) , end="") print() lst = ["{:d}*{:d}={:2d} ".format(i,j,i*j) for i in range(1,10) for j in range(1,i+1)] print(lst) # (5)求M,N中矩阵和元素的乘积 # M = [ [1,2,3], # [4,5,6], # [7,8,9] ] # N = [ [2,2,2], # [3,3,3], # [4,4,4] ] M = [ [1,2,3] ,[4,5,6] , [7,8,9] ] N = [ [2,2,2] ,[3,3,3] , [4,4,4] ] """ M[0][0] * N[0][0] = 2 M[0][1] * N[0][1] = 4 M[0][2] * N[0][2] = 6 M[1][0] * N[1][0] = 12 M[1][1] * N[1][1] = 15 M[1][2] * N[1][2] = 18 M[2][0] * N[2][0] = 12 M[2][1] * N[2][1] = 15 M[2][2] * N[2][2] = 18 """ # =>实现效果1 [2, 4, 6, 12, 15, 18, 28, 32, 36] """双层循环,外层循环动的慢,内层循环动的快,正好符号M N 矩阵的下标""" lst = [] for i in range(3): for j in range(3): lst.append( M[i][j] * N[i][j] ) print(lst) # =>实现效果2 [ [2, 4, 6], [12, 15, 18], [28, 32, 36] ] # 遍历出三个空的列表 lst = [ [] for i in range(3)] print(lst) lst = [ [ M[i][j] * N[i][j] for j in range(3) ] for i in range(3)] print(lst) """ [ M[i][j] * N[i][j] for j in range(3) ] [ [2, 4, 6] [12, 15, 18] [28, 32, 36] ] """
3. 集合_字典推导式
# ### 集合推导式 """ 案例: 满足年龄在18到21,存款大于等于5000 小于等于5500的人, 开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏) 把开卡的种类统计出来 """ lst = [ {"name":"赵沈阳","age":18,"money":3000}, {"name":"赵万里","age":19,"money":5200}, {"name":"赵蜂拥","age":20,"money":100000}, {"name":"赵世超"www.cppcns.com,"age":21,"money":1000}, {"name":"王志国","age":18,"money":5500}, {"name":"王永飞","age":99,"money":5500} ] setvar = set() for i in lst: print(i) # {'name': '赵沈阳', 'age': 18, 'money': 3000} if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500: res = "尊贵VIP卡老{}".format(i["name"][0]) else: res = "抠脚大汉卡老{}".format(i["name"][0]) # 添加到集合中 setvar.add(res) print(setvar) # { 三元运算符 + 推导式 } # 三运运算符 + 推导式 setvar = { "尊贵VIP卡老{}".format(i["name"][0]) if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500 else "抠脚大汉卡老{}".format(i["name"][0]) for i in lst } print(setvar) # ### 字典推导式 ### 一.enumerate """ enumerate(iterable,[start=0]) 功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组,通过迭代器返回 参数: iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) start: 可以选择开始的索引号(默认从0开始索引) 返回值:迭代器 """ # 基本语法 from collections import Iterator,Iterable lst =["王文","吕洞宾","何仙姑","铁拐李","张国老","曹国舅","蓝采和","韩湘子"] it = enumerate(lst) it = enumerate(lst,start=100) print(isinstance(it,Iterator)) # next print( next(it) ) # for + next (推荐,数据较大时使用) for i in range(3): print(next(it)) # for for i in it: print(i) # list 强转迭代器 print(list(it)) # (1) 字典推导式 配合 enumerate 来实现 dic = {k:v for k,v in enumerate(lst,start=100)} print(dic) """ (100, '王文') (101, '吕洞宾') (102, '何仙姑') (103, '铁拐李') (104, '张国老') (105, '曹国舅') (106, '蓝采和') (107, '韩湘子') """ # (2) 使用dict强转迭代器,瞬间得到字典 dic = dict( enumerate(lst,start=100) ) print(dic) ### 二.zip """ 特点:按照索引配对 zip(iterable, ... ...) 功能: 将多个iterable中的值,一个一个拿出来配对组成元组,通过迭代器返回 itdjyxXHtwerable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 返回: 迭代器 """ # 基本语法 # lst1 = ["孙开启","王永飞","于朝志"] # lst2 = ["薛宇健","韩瑞晓","上朝气"] # lst3 = ["刘文博","历史园","张光旭"] # 在索引下标同时存在时,才会进行配对,否则舍弃. lst1 = ["孙开启","王永飞","于朝志"] lst2 = ["薛宇健","韩瑞晓"] lst3 = ["刘文博"] it = zip(lst1,lst2,lst3) print(list(it)) # (1) 字典推导式 配合 zip 来实现 lst_key = ["ww","axd","yyt"] lst_val = ["王维","安晓东","杨元涛"] # ('ww', '王维'), ('axd', '安晓东'), ('yyt', '杨元涛') dic = {k:v for k,v in zip(lst_key , lst_val) } print(dic) # (2) 使用dict强转迭代器,瞬间得到字典 dic = dict( zip(lst_key , lst_val) ) print(dic)
4. 生成器
4.1 生成器表达式
# ### 生成器 """ #生成器本质是迭代器,允许自定义逻辑的迭代器 #迭代器和生成器区别: 迭代器本身是系统内置的.重写不了. 而生成器是用户自定义的,可以重写迭代逻辑 #生成器可以用两种方式创建: (1)生成器表达式 (里面是推导式,外面用圆括号) (2)生成器函数 (用def定义,里面含有yield) """ # (1) 生成器表达式 (里面是推导式,外面用圆括号) gen = ( i for i in range(10) ) print(gen) # 判断类型 from collections import Iterator,Iterable print(isinstance(gen,Iterator)) # 1.next 调用生成器 print(next(gen)) print(next(gen)) # 2.for + next 调用生成器 for i in range(3): print(next(gen)) # 3.for 调用生成器所有数据 for i in gen: print(i) # 4.list强转生成器,瞬间得到所有数据 gen = ( i for i in range(10) ) print(list(gen)) # print(next(gen)) er编程客栈ror # StopIteration
4.2 生成器函数
# ### 生成器函数 """ # yield 类似于 return 共同点在于:执行到这句话都会把值返回出去 不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走 而return直接终止函数,每次重头调用. yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用 """ # (1) 基本语法 def mygen(): print("111") yield 1 print("222") yield 2 print("333") yield 3 # 初始化生成器函数 => 返回生成器对象 => 简称生成器 gen = mygen() # 第一次调用 res = next(gen) print(res) # 第二次调用 res = next(gen) print(res) # 第三次调用 res = next(gen) print(res) # 第四次调用 """ StopIteration error res = next(gen) print(res) """ """ # 第一次调用 print("111") yield 1 保存当前第13行代码的状态,把1返回,并且等待下一次调用 # 第二次调用 从上一次保存的位置13行往下走, print("222") yield 2 保存当前第16行代码的状态,把2返回,并且等待下一次调用 # 第三次调用 从上一次保存的位置16行往下走, print("333") yield 3 保存当前第19行代码的状态,把3返回,并且等待下一次调用 # 第四次调用 因为没有更多的yield 返回数据,所有停止迭代.出现报错异常. """ # (2) 优化生成器代码 """生成器应用的场景是在大数据的范围中使用,切记不可直接用for遍历所有,可能无法短时间内获取所有数据""" def mygen(): for i in range(1,101): yield i # 初始化生成器函数 => 生成器 gen = mygen() print("<=====>"www.cppcns.com) for i in range(30): num = next(gen) print("我的球衣号码是{}".format(num)) print("<=====>") for i in range(40): num = next(gen) print("我的球衣号码是{}".format(num)) # (3) send的使用方式 (给上一个yield发送数据) """ # next和send区别: next 只能取值 send 不但能取值,还能发送值 # send注意点: 第一个 send 不能给 yield 传值 默认只能写None 最后一个yield 接受不到send的发送值 """ def mygen(): print("start") res = yield "内部1" print(res,"<==内部==>") res = yield "内部2" print(res,"<==内部==>") res = yield "内部3" print(res,"<==内部==>") print("end") # 初始化生成器函数 => 生成器 gen = mygen() # 第一次调用生成器 """ 第一次调用生成器时,因为没有遇到yield保存的代码位置, 无法发送数据,默认第一次只能发送None """ res = gen.send(None) print(res,"<==外部==>") # 第二次调用生成器 res = gen.send("100") print(res,"<==外部==>") # 第三次调用生成器 res = gen.send("200") print(res,"<==外部==>") # 第四次调用生成器 """ error res = gen.send("300") print(res,"<==外部==>") """ """ 使用send调用生成器,第一次发送时必须是None,因为还没有遇到yield保存的代码位置 res = gen.send(None) 走到mygen生成器函数中 print("start") res = yield "内部1" 执行第80行 ,保存退出,记录当前代码位置,将 "内部1" 返回 在98行接受数据 res = "内部1" print(内部1,"<==外部==>") 第二次调用生成器 res = gen.send("100") 把100这个数据发送给上一次代码保存的位置80行进行接受. => 导致 80行 res = 100 打印81行 print(100 ,"<==内部==>") 执行83行 res = yield "内部2" 保存退出,记录当前代码位置,将 "内部2" 返回 执行102行 res = gen.send("100") => "内部2" print("内部2","<==外部==>") .... 依次类推 ... 到第四次调用时, 因为没有更多的yield 返回数据,gen.send(300)无法接受到返回值,所以出现停止迭代 StopIteration的报错,程序终止; """ # (4) yield from 的使用 """将一个可迭代对象变成一个迭代器返回 """ def mygen(): lst = ["张磊","李亚峰","刘一峰","王同培"] yield from lst # 初始化生成器函数 gen = mygen() print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen)) # print(next(gen)) # StopIteration # (5) 斐波那契数列 """使用生成器分段获取所有内容,而不是一股脑的把所有数据全部打印""" """1 1 2 3 5 8 13 21 34 .... """ def mygen(maxval): a,b = 0,1 i = 0 while i < maxval: # print(b) yield b a,b = b,a+b i += 1 # mygen(10) gen = mygen(10) # 第一次获取 for i in range(3): print(next(gen)) # 第二次获取 for i in range(5): print(next(gen))
5. 小练习
# 1.用推导式写如下程序 # (1)构建如下列表:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] lst = [i * 2 for i in range(10)] lst = [i for i in range(0,19,2) ] print(lst) # (2)lst = ['alex', 'WuSir', '老男孩', '神秘男孩'] 将lst构建如下列表:['alex0', 'WuSir1', '老男孩2', '神秘男孩3'] lst = ['alex', 'WuSir', '老男孩', '神秘男孩'] # 方法一 # lst = [i + str(lst.index(i)) for i in lst] # 方法二 lst = [lst[i] + str(i) for i in range(len(lst)) ] print(lst) # (3)构建如下列表:[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] lst = [ (j,i) for j in range(0,6) for i in range(1,7) if i-j == 1] print(lst) lst = [(i,i+1) for i in range(6)] print(lst) # (4)求出50以内能被3整除的数的平方,并放入到一个列表中。 lst = [i ** 2 for i in range(51) if i % 3 == 0] print(lst) # (5)M = [[1,2,3],[4,5,6],[7,8,9]], 把M中3,6,9组成新列表 M = [[1,2,3],[4,5,6],[7,8,9]] lst = [ i[-1] for i in M ] print(lst) # (6)构建如下列表:['python1期', 'python2期', 'python3期', 'python4期', 'python6期', 'python7期', 'python8期', 'python9期', 'python10期'] lst = [ "python{}期".format(i) for i in range(1,11) if i != 5 ] print(lst) # (7)过滤掉长度小于3的字符串列表 , 并转换成大写字母 lst = ["sdfsdfsdfsdf","234","你说的符号是","a","ab"] lst = [ i.upper() for i in lst if len(i) >=3 ] print(lst) # (8)除了大小王,里面有52项,每一项是一个元组,请返回如下扑克牌列表[('红心','2'),('草花','J'), …('黑桃','A')] lst1 = ["红心","草花","黑桃","方片"] lst2 = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"] lst = [(i,j) for i in lst1 for j in lst2] print(lst) # 2.用推导式写如下程序 lst1 = { 'name':'alex', 'Values':[ {'timestamp': 1517991992.94,'values':100,}, {'timestamp': 1517992000.94,'values': 200,}, {'timestamp': 1517992014.94,'values': 300,}, {'timestamp': 1517992744.94,'values': 350}, {'timestamp': 1517992800.94,'values': 280} ] } # 将lst1 转化成如下 lst2: lst2 = [ [1517991992.94, 100], [1517992000.94, 200], [1517992014.94, 300], [1517992744.94, 350], [1517992800.94, 280] ] # 方法一 lst2 = [ [i["timestamp"] , i["values"]] for i in lst1["Values"] ] print(lst2) # 方法二 lst2 = [ list(i.values()) for i in lst1["Values"]] print(lst2) # 3.读取一个文件所有内容,通过生成器调用一次获取一行数据. def mygen(filename): with open(filename,mode="r+",encoding="utf-8") as fp: for i in fp: yield i gen = mygen("ceshi111.txt") for i in range(3): print(next(gen)) for i in range(6): print(next(gen)) # 4.将普通求和函数改写成yield写法 print("<====>") def add(a,b): yield a + b mygen = add(34,5) for i in mygen: print(i)
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!
精彩评论