1. 生成器
# 生成器的本质就是迭代器 # 生成器的特点和迭代器一样,取值方式和迭代器一样(__next__(), send(): 给上一个yield传值 # 生成器其实就是手写的迭代器 生成器的三种生成办法: 1.通过生成器函数* 2.通过生成器表达式创建生成器* 3.通过数据转换(这次没学)
2. 生成器函数
1. 什么是生成器函数
# 函数中有yield,name这个函数就是生成器函数
def func(): print("我是周杰伦") yield "昆凌" # 函数中包含了yield, 当前这个函数就不再是普通的函数了. 是生成器函数 print("我是王力宏") yield "李云迪???" print("我是笛卡尔积") yield "笛卡尔积是谁" # print("你好啊") # 最后一个yield之后如果再进行__next__ 会报错 g = func() # 不会执行函数, 拿到的是生成器. print(g.__next__()) # 周杰伦 print(g.__next__()) # 王力宏 print(g.__next__()) # 笛卡尔积 print(g.__next__()) # 执行下一个yield # 函数中如果有yield 这个函数就是生成器函数. 生成器函数() 获取的是生成器. 这个时候不执行函数 # return 直接返回结果, 结束函数的调用 # yield 返回结果, 可以让函数分段执行 # g.__next__() # 执行函数. 执行到下一个yield # g.__next__() # 继续执行函数到下一个yield
2. 生成器的好处之一: 不占用内存
# 一次性拿出所有的放在列表里,占用内存 def order(): lst = [] for i in range(1000): lst.append("衣服" + str(i)) return lst ret = order() print(ret) # 生成器,一次拿出一个,不占用内存 def order(): for i in range(1000): yield "衣服" + str(i) g = order() # 获取生成器,不执行函数 mingwei = g.__next__() print(mingwei) # 衣服0 zhaoyining = g.__next__() print(zhaoyining) # 衣服1
3. send()方法 # send() 和 __next__是一样的. 可以执行到下一个yield # send() 还可以给上一个yield位置传值, 不能给最后⼀个yield发送值. 在第⼀次执⾏⽣成器代码的时候不能使⽤send() 例1: def func(): print("我是第一段") a = yield 123 print(a) print("闫子哲是第二段") b = yield 456 print(b) print("理想是第三段") c = yield 789 print(c) print("刘伟是最后一段") d = yield 666 # 最后收尾一定是yield g = func() # 获取生成器,不执行函数 print(g.__next__()) # 没有上一个yield 所以不能使用send() 开头必须是__next__() print(g.send("煎饼果子")) print(g.send("韭菜盒子")) print(g.send("锅包肉")) 例2: def eat(): print("我吃什么啊") a = yield "馒头" print("a=",a) b = yield "⼤饼" print("b=",b) c = yield "⾲菜盒⼦" print("c=",c) yield "GAME OVER" gen = eat() # 获取⽣成器 ret1 = gen.__next__() print(ret1) # 馒头 ret2 = gen.send("胡辣汤") print(ret2) ret3 = gen.send("狗粮") print(ret3) ret4 = gen.send("猫粮") print(ret4)
4. 拿生成器里所有的东西
def func(): yield 1 yield 13 yield 26 yield 88 yield 46 # 现在func() 是生成器,然后for迭代生成器 for i in func(): # for的内部一定有__next__() print(i) 结果: 1 13 26 88 46 # 还可以这样拿所有值 print(list(func())) # 内部都有__next__() 结果: [1, 13, 26, 88, 46]
4. 各种推导式
1. 列表推导式 lst = [] for i in range(1, 16): lst.append("python" + str(i)) print(lst) 列表推导式: 用一句话生成一个列表 lst = ["python"+str(j) for j in range(1, 16)] print(lst) 语法: [结果 for循环 判断] 例1: # 100以内的奇数 lst = [i for i in range(100) if i%2==1] print(lst) 例2: # 100以内能被3整除的数的平方 lst = [i*i for i in range(100) if i%3==0] print(lst) 例3: # 寻找名字中带有两个e的⼈的名字 names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] # for循环完成 lst = [] for line in names: for name in line: if name.count("e") == 2: lst.append(name) print(lst) # 列表推导式完成 lst = [name for line in names for name in line if name.count("e") == 2] print(lst)
2. 字典推导式 # 把[11, 22, 33, 44] 变成 {0:11,1:22,2;33} lst = [11, 22, 33, 44] dic = {i:lst[i] for i in range(len(lst)) if i < 2} # 字典推导式就一行 print(dic) 语法: {k:v for循环 条件筛选} 例1: # 把key和value位置反过来 dic = {"JJ": "林俊杰", "jay": "周杰伦", "zs": "赵四", "ln": "刘能"} dic = {v: k for k, v in dic.items()} print(dic)
3. set(集合)推导式 首先再来回顾一下set(集合): 1. set去重复 2. set本身是不可哈希的(可变的) 3. set中的元素是可哈希的(不可变的) # 集合推导式 s = {i for i in range(100)} # 可去重复 print(s) 语法: {i for循环 条件判断} 例: 将数据去重
lst = [1, 1, 4, 6, 7, 4, 2, 2] # 转换成集合再转换回去 s = set(lst) print(s) 结果: {1, 2, 4, 6, 7} # 直接用集合推导式 s = {el for el in lst} print(s) 结果: {1, 2, 4, 6, 7}
5. 生成器表达式
# 生成器表达式 tu = (i for i in range(10)) # 没有元组推导式. 生成器表达式 print(tu) # 生成器 print(tu.__next__()) # 0 print(tu.__next__()) # 1 print(tu.__next__()) # 2 print(tu.__next__()) # 3 print(tu.__next__()) # 4 print(tu.__next__()) # 5 print(tu.__next__()) # 6 print(tu.__next__()) # 7 print(tu.__next__()) # 8 print(tu.__next__()) # 9 print(tu.__next__()) # 第11个报错 # 生成机制比较 lst = [i for i in range(10)] # 列表一下子拿出所有值 print(lst) 结果: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] gen = (i for i in range(10)) # 生成器, 惰性机制(要一个值,给一个值) print(gen.__next__()) 结果: 0
# 深坑==> ⽣成器. 要值得时候才拿值. (这个值拿过就没有了) 例1: # 生成器函数 def func(): print(111) yield 222 yield 333 g = func() # 获取生成器 g1 = (i for i in g) # 生成器 g2 = (i for i in g1) # 生成器 print(list(g)) # ??? [222]. g从源头func()把数据拿走了 print(list(g1)) # ??? [] g1找g要数据,g找源头拿数据,源头已经没有数据了 print(list(g2)) # ??? [] 同理g1 例2: # 分析这道面试题 # 求和 def add(a, b): return a + b # 生成器函数 # 0-3 def test(): for r_i in range(4): yield r_i # 0,1,2,3 g = test() # 获取生成器 # 懒 for n in [2, 10]: g = (add(n, i) for i in g) # 到最后往里面放值就对了(不到最后不往里面放值) print(list(g)) # 获取生成器里面的所有值 结果: [20, 21, 22, 23]
print(list(g)) # g里面的东西取完了 第二次再拿就是[] 结果: []