1. 推导式(列表推导式、集合推导式、字典推导式)
# ### 推导式 : 通过一行循环判断,遍历出一系列数据的方式是推导式 """ 推导式一共三种: 列表推导式,集合推导式,字典推导式 [val for val in Iterable] {val for val in Iterable} {a:b for a,b in iterable} """ # (1)单循环的推导式 """[1,2,3,4,5,6,7,8 ... 50]""" lst = [] for i in range(1,51): print(i) lst.append(i) print(lst) # 改写成推导式 lst = [val for val in range(1,51)] print(lst) # (2)带有判断条件的单循环推导式 [判断条件只能是单项分支,其他的不可以] """[1,2,3,4,5,6,7,8 ... 50] 要所有的偶数""" lst = [] for i in range(1,51): if i % 2 == 0: lst.append(i) print(lst) # 改写成推导式 lst = [i for i in range(1,51) if i % 2 == 0] print(lst) # (3)多循环推导式 "谁❤谁" lst1 = ["常远","皮得意","纸质红"] lst2 = ["李德亮","林明辉","陈佳琪"] lst_new = [] for i in lst1: for j in lst2: strvar = i + "❤" + j lst_new.append(strvar) print(lst_new) # 改写成推导式 lst = [i + "❤" + j for i in lst1 for j in lst2] print(lst) # (4)带有判断条件的多循环推导式 lst1 = ["常远","皮得意","纸质红"] lst2 = ["李德亮","林明辉","陈佳琪"] lst_new = [] for i in lst1: for j in lst2: if lst1.index(i) == lst2.index(j): strvar = i + "❤" + j lst_new.append(strvar) print(lst_new) # 改写成推导式 lst = [i + "❤" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j)] print(lst)
# (1).{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式 dic = {'x': 'A', 'y': 'B', 'z': 'C' } lst = [k+"="+v for k,v in dic.items()] print(lst) # (2).把列表中所有字符变成小写 ["ADDD","dddDD","DDaa","sss"] lst = ["ADDD","dddDD","DDaa","sss"] lst_new = [i.lower() for i in lst] print(lst_new) # (3).x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中 # (0,1) (0,3) (0,5) # (2,1) (2,3) (2,5) # (4,1) (4,3) (4,5) # 方法一 lst = [] for i in range(6): for j in range(6): if i % 2 == 0 and j % 2 == 1: res = (i,j) lst.append(res) print(lst) # 改写成推导式 lst = [(i,j) for i in range(6) for j in range(6) if i % 2 == 0 and j % 2 == 1] print(lst) # 方法二 lst = [] for i in range(6): if i % 2 == 0: for j in range(6): if j % 2 == 1: res = (i,j) lst.append(res) print(lst) # 改写成推导式 lst = [(i,j) for i in range(6) if i % 2 == 0 for j in range(6) if j % 2 == 1 ] print(lst) # (4).使用列表推导式 制作所有99乘法表中的运算 for i in range(1,10): for j in range(1,i+1): print("%d*%d=%2d " % (i,j,i*j),end="") print() # 改写成推导式 lst = ["%d*%d=%2d " % (i,j,i*j) for i in range(1,10) for j in range(1,i+1) ] print(lst) for i in range(9,0,-1): for j in range(1,i+1): print("%d*%d=%2d " % (i,j,i*j),end="") print() # 改写成推导式 lst = ["%d*%d=%2d " % (i,j,i*j) for i in range(9,0,-1) 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] ] # =>实现效果1 [2, 4, 6, 12, 15, 18, 28, 32, 36] # =>实现效果2 [[2, 4, 6], [12, 15, 18], [28, 32, 36]] 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] 16 M[2][0] * N[2][0] 28 M[2][1] * N[2][1] 32 M[2][2] * N[2][2] 36 """ # =>实现效果1 [2, 4, 6, 12, 15, 18, 28, 32, 36] # lst = [(i,j) for i in range(3) for j in range(3)] # print(lst) lst = [M[i][j] * N[i][j] for i in range(3) for j in range(3)] print(lst) # =>实现效果2 [[2, 4, 6], [12, 15, 18], [28, 32, 36]] # lst = [5 for i in range(3)] # lst = [[] for i in range(3)] # print(lst) # lst = [ [(i,j) for j in range(3)] for i in range(3) ] lst = [ [ M[i][j]*N[i][j] for j in range(3) ] for i in range(3) ] print(lst)
# ### 集合推导式 """ 案例: 满足年龄在18到21,存款大于等于5000 小于等于5500的人, 开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏) 把开卡的种类统计出来 """ listvar = [ {"name":"王家辉","age":18,"money":10000}, {"name":"王水机","age":19,"money":5100}, {"name":"王鹏","age":20,"money":4800}, {"name":"李站","age":21,"money":2000}, {"name":"李小龙","age":180,"money":20} ] setvar = set() for i in listvar: if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500: res = "尊贵VIP卡老" + i["name"][0] else: res = "抠脚大汉卡老" + i["name"][0] # 把最后的元素添加到集合中 setvar.add(res) print(setvar) """三目运算符 : 真区间值 if 条件表达式 else 假区间值""" setvar = { "尊贵VIP卡老" + i["name"][0] if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500 else "抠脚大汉卡老" + i["name"][0] for i in listvar } print(setvar) # ### 字典推导式 ### (1)enumerate """ enumerate(iterable,[start=0]) 功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中 参数: iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) start: 可以选择开始的索引号(默认从0开始索引) 返回值:迭代器 """ from collections import Iterator,Iterable # 基本语法 listvar = ["张龙","余泽民","众赞林"] it = enumerate(listvar) print(it) res = isinstance(it,Iterator) print(res) # (1) next """ res = next(it) print(res) res = next(it) print(res) res = next(it) print(res) """ # for """ for i in it: print(i) """ # for + next """ for i in range(2): res = next(it) print(res) """ # list """ lst = list(it) print(lst) """ # 从5下标开始枚举 lst= list( enumerate(listvar,start=5) ) print(lst) # 1.转化成字典推导式变成字典 listvar = ["张龙","余泽民","众赞林"] dic = {a:b for a,b in enumerate(listvar) } dic = {a:b for a,b in enumerate(listvar,start = 5) } print(dic) # 2.dict 用dict强转迭代器变成字典 dic = dict( enumerate(listvar ) ) print(dic) # (2) zip """ zip(iterable, ... ...) 功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中 iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 返回: 迭代器 多出来无人配对的元素,会自动的舍掉; """ # 基本语法 lst1 = ["刘守乱","马训","周冰洁"] lst2 = ["郭少东","罗启云","尹家平"] lst3 = ["郭少东1","罗启云2"] it = zip(lst1,lst2,lst3) print(isinstance(it , Iterator)) # 使用list强转迭代器 lst = list(it) print(lst) # 用zip 形成字典推导式 变成字典 lst1 = ["a","b","c"] lst2 = [1,2,3] dic = { k:v for k,v in zip(lst1,lst2) } print(dic) # 用dict 强制转换zip形成的迭代器 变成字典 dic = dict( zip(lst1,lst2) ) print(dic) # 小案例 把dic1中的键和dic2中的值 组合在一起变成新字典; dic1 = {"cpx":"身材高大魁梧","zjc":"爱走神","zyl":"活泼好动"} dic2 = {"a":"曹培显","b":"主进程","c":"周永玲"} container1 = dic1.keys() print(container1) container2 = dic2.values() print(container2) # res = list( zip(container1,container2) ) # print(res) # 1.通过dict 强制转换变成字典 dic = dict( zip(container1,container2) ) print(dic ) # 2.使用推导式配合zip 变成字典 dic = {k:v for k,v in zip(container1,container2)} print(dic)
2. 生成器与生成器函数
# ### 生成器 """ #生成器本质是迭代器,允许自定义逻辑的迭代器 #迭代器和生成器区别: 迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑 #生成器可以用两种方式创建: (1)生成器表达式 (里面是推导式,外面用圆括号) (2)生成器函数 (用def定义,里面含有yield) """ from collections import Iterator , Iterable # (1) 生成器表达式 generator gen = ( i for i in range(5) ) print(gen) res = isinstance(gen,Iterator) print(res) # (2) 获取生成器中的数据 # 1. next res = next(gen) print(res) res = next(gen) print(res) res = next(gen) print(res) res = next(gen) print(res) res = next(gen) print(res) # res = next(gen) error # print(res) # 2.for gen = ( i for i in range(5) ) for i in gen: print(i) # 3.list gen = ( i for i in range(5) ) lst = list(gen) print(lst) # 4 for + next gen = ( i for i in range(5) ) for i in range(2): res = next(gen) print(res)
# ### 生成器函数 """ # yield 类似于 return 共同点在于:执行到这句话都会把值返回出去 不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走 而return直接终止函数,每次重头调用. yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用 """ # (1) 基本语法 # 生成器函数 def mygen(): print("one") yield 1 print("two") yield 2 print("three") yield 3 # 初始化生成器函数 -> 生成器对象 -> 简称生成器 gen = mygen() print(gen) # 调用生成器 res = next(gen) # 第一次调用生成器 print(res) res = next(gen) # 第二次调用生成器 print(res) res = next(gen) # 第三次调用生成器 print(res) # res = next(gen) # error # 第四次调用生成器 # print(res) """ 初始化生成器函数 第一次调用生成器 res = next(gen) print(one) yield 1 记录当前代码执行的状态,将1返回,返回到调用处,阻塞等待下一次调用 第二次调用生成器 res = next(gen) 从13行,上一次记录的位置,往下执行 , print(two) yield 2 记录当前代码执行的状态,将2返回,返回到调用处,阻塞等待下一次调用 第三次调用生成器 res = next(gen ) 从16行,上一次记录的位置,往下执行 , print(three) yield 3 记录当前代码执行的状态,将3返回,返回到调用处,阻塞等待下一次调用 第四次调用生成器 从19行继续向下执行,发现没有yield 了 ,没有数据可以返回, 直接报错; """ # (2) 改造生成器 def func(): for i in range(1,101): yield "球衣号码{}".format(i) # 初始化生成器函数 -> 生成器对象 -> 简称生成器 gen = func() for i in range(50): res = next(gen) print(res) for i in range(30): res = next(gen) print(res) # (3) send send是把数据发送给上一个yield """ ### send # next和send区别: next 只能取值 send 不但能取值,还能发送值 # send注意点: 第一个 send 不能给 yield 传值 默认只能写None 最后一个yield 接受不到send的发送值 """ def mygen(): print("start") res1 = yield 1 print(res1) res2 = yield 2 print(res2) res3 = yield 3 print(res3) print("end") # 初始化生成器函数 -> 生成器对象 -> 生成器 gen = mygen() # 因为要发送给上一个yield , 第一次发送只能None val1 = gen.send(None) print(val1) print("<====>") val2 = gen.send("one") print(val2) print("<====>") val3 = gen.send("two") print(val3) # 最后一次调用,因为没有yield 直接越界报错 # val4 = gen.send("three") # print(val4) """ val1 = gen.send(None) 第一次发送 因为要发送给上一个yield ,所以只能是None print("start") 走到 81 行 ,记录当前代码执行的状态,将1返回,val1接受数据,添加阻塞,等待下一次调用 第二次发送 val2 = gen.send("one") 81行记录的状态往下执行,yield 1 接收到send 发送过来的数据"one" res1 = "one" print(pme) 走到 84 行 ,res2 = yield 2 , 记录当前代码执行的状态,将2返回,val2接受数据,添加阻塞,等待下一次调用 第三次发送 val3 = gen.send("two") 84行记录的状态往下执行, yield 2 接收到send 发送过来的数据"two" res2 = "two" print(two) 走到 87 行 ,res3 = yield 3, 记录当前代码执行的状态,将3返回,val3接受数据,添加阻塞,等待下一次调用 第四次发送 从87行往下执行 print(res3) print("end") 因为没有yield 返回数据, StopIteration 越界错误; """ # (4)yield from : 将一个可迭代对象变成一个迭代器返回 def mygen(): yield from [1,2,3,4] gen = mygen() res = next(gen) print(res) res = next(gen) print(res) res = next(gen) print(res) res = next(gen) print(res) # (5) 斐波那契数列 # 1 1 2 3 5 8 13 21 34 55 .... # a = 0 # b = 1 # a,b = b,a+b # print(a,b) # a,b = b,a+b # print(a,b) # a,b = b,a+b # print(a,b) # a,b = b,a+b # print(a,b) # a,b = b,a+b # print(a,b) # a,b = b,a+b print("<=====>") def myfib(maxlength): a,b = 0,1 i = 0 while i<maxlength: # print(b) yield b a,b = b,a+b i+=1 # 生成器函数 => 生成器对象 gen = myfib(10) # for i in gen: # print(i) for i in range(3): res = next(gen) print(res)
day12