推导式及生成器
1、推导式 (comprehensions)
# 语法 ---> var for var in iterable
1.1 列表推导式
# res = [var for var in iterable ] # 基本语法 print([i for i in range(100)]) # 单循环 + 判断 print([i for i in range(100) if i % 2 == 1]) # 双循环 + 判断 lst1 = ["中国","美国","牙买加"] lst2 = ["黄种人","白种人","黑种人"] print([i + ":" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j)])
1.1.1 列表推导式练习题
(1).{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式 dic = {'x': 'A', 'y': 'B', 'z': 'C' } print([ k + "=" + v for k,v in dic.items()]) (2).把列表中所有字符变成小写 ["ADDD","dddDD","DDaa","sss"] lst = ["ADDD","dddDD","DDaa","sss"] print([i.lower() for i in lst]) (3).x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中 print([(x,y) for x in range(0,5,2) for y in range(1,6,2)]) (4).使用列表推导式 制作所有99乘法表中的运算 print(["{}*{}={:2d}".format(i,j,i*j) for i in range(1,9) for j in range(1,i+1)]) (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]]j res1 = [M[i][j]*N[i][j] for i in range(3) for j in range(3)] res2 = [[M[i][j]*N[i][j] for j in range(3) ] for i in range(3)]
1.2 集合推导式
# res = {var for var in iterable} ---> 去重,无序 (一般用于统计种类) """ 案例: 满足年龄在18到21,存款大于等于5000 小于等于5500的人, 开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏) 把开卡的种类统计出来 """ listvar = [ {"name":"赵一","age":18,"money":9000}, {"name":"钱二","age":19,"money":5100}, {"name":"孙三","age":20,"money":4800}, {"name":"李四","age":21,"money":2000}, {"name":"周五","age":18,"money":1480} ] # 常规写法 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) # 改写成集合推导式 ---> {三元运算符 + 推导式} 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.3 字典推导式
# {k,v for k,v in iterable} # iterable 必须是等长二级容器,且个数为二
1.3.1 enumerate ,zip
# enumerate (iterable,start=0) """ 功能:枚举 ---> 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中 参数: iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) start: 可以选择开始的索引号(默认从0开始索引) 返回值:迭代器 """ lst = ["赵","钱","孙","李","周","吴","郑","王"] res = enumerate(lst,start=1) # [(1, '赵'),(2, '钱'),(3, '孙'),(4, '李'),(5, '周'),(6, '吴'),(7, '郑'),(8, '王')] print(list(res)) # zip (iterable1, iterable2,...) """ 功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中 iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 返回: 迭代器 特征: 如果找不到对应配对的元素,当前元素会被舍弃 """ lst1 = [1,2,3,4,5] lst2 = ["赵","钱","孙","李","周","吴","郑","王"] print(list(zip(lst1,lst2))) # [(1, '赵'), (2, '钱'), (3, '孙'), (4, '李'), (5, '周')]
1.3.2 字典推导式
lst1 = [1,2,3,4,5] lst2 = ["赵","钱","孙","李","周","吴","郑","王"] # 利用 enumerate 形成字典 res = { k:v for k,v in enumerate(lst2,start=1)} # 利用 zip 形成字典 res = { k:v for k,v in zip(lst1,lst2)} # dict 强转字典 res = dict(enumerate(lst2,start=1)) res = dict(zip(lst1,lst2))
2、生成器 (generator)
# 生成器本质是迭代器,允许自定义逻辑的迭代器 # 迭代器和生成器区别:迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑 # 生成器可以用两种方式创建: (1)生成器表达式 (里面是推导式,外面用圆括号) (2)生成器函数 (用def定义,里面含有yield) yield 与 return 共同点于:执行到这句话都会把值返回出去 不同点: yield 每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走, 而return直接终止函数,每次重头调用. yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
2.1 生成器函数
# 定义 def func() print("执行生成器") yield 1 # 初始化生成器函数,返回生成器对象,简称生成器 gen_func = func() # 调用生成器 res = next(gen_func) # 执行生成器 print(res) # 打印 yield 返回值
2.1.1 生成器函数的应用示例
def func(): for i in range(1,101): yield "该球衣号码是{}".format(i) # 初始化生成器函数 gen_func = func() # 调用生成器 (生成10次) for i in range(10): res = next(gen_func) print(res) # 再次生成从上一次停止位置开始执行 res = next(gen_func) print(res) # 重置生成器 gen_func1 = func()
2.1.2 send 方法
""" next 和 send 区别: next 只能取值 send 不但能取值,还能发送值 send 注意点: 第一个 send 不能给 yield 传值 默认只能写None 最后一个yield 接受不到send的发送值 send 是给上一个yield发送值 """ # 示例 def func(): print("process start") res = yield 100 print(res,"内部打印1") res = yield 200 print(res,"内部打印2") res = yield 300 print(res,"内部打印3") print("process end") # 初始化生成器函数 gen_func = func() # 调用生成器 res = gen_func.send(None) # process start 生成器刚启动,send 无法给上一个 yield 传值 print(res) # 打印第一个 yield 返回值 100 res = gen_func.send(500) # send 将500传给上一个 yield 也就是 res = 500 ,内部打印1 print(res) # 打印第二个 yield 返回值 200
2.1.3 yield from 方法
# 返回值:将一个可迭代对象变成一个迭代器 def func() yield from [i for i in range(10)] # 初始化生成器函数 gen_func = func() # 调用 for i in gen_func: print(i)
2.2 生成器表达式
# (var for var in iterable) res = (i for i in range(500)) print(list(res))
3、迭代器调用的方式
# 方式一 next() (手动触发,一次取一值) # 方式二 __iter__ (解释器自动除发,不推荐使用) # 方式三 for (遍历,当数量大时,需控制好遍历数量) # 方式四 强转 (list等)