生成器以及面试题
1.生成器
背景:列表太占内存,所以我们想要多少取多少
本质是迭代器 写法和迭代器不一样 用法一样
return和yield都可以返回数据
特点:
1.节省内存 几乎不占用内存
2.惰性机制
3.只能往前走
# 找不到yield报错
# 对程序效率提升特别大
#send()也可以实现类似__next__()效果
给上一个yield传值
获取下一条值得效果基本一致
接收当前yield的值 同时把给上一条yield赋值
#send不可以在开头
#最后一个
send和next的区别:
send不可以在开头
#send不可以在开头
send可以给上一个yield传值,不能给最后一个yield传值
#生成器可以直接使用for循环
#生成器也可以转化为列表
2.生成器函数
g = func() # 啥都没做
1.send #第一次不用send
2.函数中的最后一个yield不能接受新的值
3.预激生成器的装饰器例子
3.各种推导式 ===>列表/字典/集合/“元组”(生成器)
元组没有推导式
生成器表达式:(结果 for if)
可以直接使用生成器表达式直接创建生成器:gen = (i for i in range(10))
生成器表达式/列表推导式
列表推导式:一次性把所有的数据创建出来,容易产生内存浪费
生成器表达式:记录一下代码。每次需要的时候去生成器里面执行一次代码
特性:
1.节省内存
2.惰性机制
3.只能向前
4.python3里面的新语法yield from
下面这两个函数的骚操作是一样的:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def func(): 2 s1 = 'test' 3 for i in s1: 4 yield i 5 6 7 g = func() 8 for i in g: 9 print(i, end=" ") 10 11 12 def func1(): 13 s1 = 'test' 14 yield from s1 15 16 17 g = func1() 18 for i in g: 19 print(i, end=" ") 20 """ 21 t e s t t e s t 22 """
5.生成器表达式(笔试题)
1.带装饰器的生成器获取平均值(有点像C语言里面的链表) ====>这个代码实在是太经典了 多撸几遍
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def init(f): 2 def inner(*args, **kwargs): 3 g = f(*args, **kwargs) 4 g.__next__() 5 return g 6 7 return inner 8 9 10 @init # average = init(average) 11 def average(): 12 sum1 = 0 13 count = 0 14 avg = 0 15 while True: 16 num = yield avg 17 count += 1 18 sum1 += num 19 avg = sum1 / count 20 21 22 g = average() 23 # g.__next__() # 可以加一个装饰器把这句话纳入收起来 24 print(g.send(10)) 25 print(g.send(110)) 26 """ 27 10.0 28 60.0 29 """
2.生成器函数和生成器表达式混合(此题难度系数:让无数英雄竞折腰)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 面试题 2 def demo(): 3 for i in range(4): 4 yield i 5 6 7 g = demo() 8 g1 = (i for i in g) 9 g2 = (i for i in g1) 10 # g2 = (i for i in (i for i in demo())) # 等价于这个 11 print(list(g1)) 12 print(list(g2)) 13 """ 14 [0, 1, 2, 3] 15 [] 16 """
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def add(n, i): 2 return n + i 3 4 5 def test(): 6 for i in range(0, 10, 2): 7 yield i 8 9 10 g = test() 11 for n in [1, 10, 4, 20]: 12 g = (add(n, i) for i in g) 13 """ 14 上面的骚操作拆开来看,实际上就等于下面这几步 15 n = 2 16 g = (add(n, i) for i in test()) 17 18 n = 10 19 g = (add(n, i) for i in (add(n, i) for i in test())) 20 因为惰性机制 直到打印的时候才去取值 21 所以实际上 嵌套的列表里面的最后一个值 起作用 22 并且有几个值就起了几次作用 23 """ 24 print(list(g))