生成器进阶
def func():
yield 1
yield 2
yield 3
g = func()
for i in g:
print(i) # 1
print(list(g)) #[2,3]
-1. 生成器里面的值只能被顺序的取一次,取完就没有了
-2. 生成器里面的值用的时候才取
send()
-send和nex一样 也会走一步到下一个yield停止
- send和next工作的起止位置是完全相同的
- send可以把一个值作为信号量传递到函数中去
- 在生成器执行伊始,只能先用next
- 只要用send传递参数的时候,必须在生成器中还有一个未被返回的yield
- send()必须传值!但生成器里面可以不接收
def wrapper(func): #生成器预激装饰器 def inner(*args,**kwargs): g = func(*args,**kwargs) #g = average_func() g.__next__() return g return inner @wrapper def average_func(): #求往天利率平均值 total = 0 count = 0 average = 0 while True: value = yield average #0 30.0 25.0 total += value #30 50 count += 1 #1 2 average = total/count #30 25 g = average_func() print(g.send(30))
def func(): print(1) yield 2 print(3) value = yield 4 print(5) yield value g = func() print(g.__next__()) print(g.send(88)) print(g.__next__()) #输出 1 2 3 4 5 None
生成器面试题
def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g=test()
for n in [1,10,5]:
g=(add(n,i) for i in g)
print(list(g))
#[15,16,17,18]
解析:重点是for循环店是一个列表,不管多少次i都是最后一个值
def add(n,i): return n+i def test(): for i in range(4): yield i g=test() g=(add(5,i) for i in [0,1,2,3])#5,6,7,8 g=(add(5,i) for i in [5,6,7,8])#10,11,12,13 g=(add(5,i) for i in [0,11,12,13])##[15,16,17,18] print(list(g))
列表推导式
new_l = []
for i in [1,3,5]:
new_l.append(i*i)
print(new_l)
print([i*i for i in [1,3,5]]) #结果必须是一个列表
l = [{'name':'alex','age':80},{'name':'egon','age':40},{'name':'yuan','age':30},{'name':'nezha','age':18}]
print([dic['name'] for dic in l]) #所有的name
print([d['name'] for d in l if d['age'] > 18]) #年龄大于18的所有人的名字
#30以内能被3整除的数
[0,1,2,3,4,5,6] = [0,3,6]
print([num for num in range(30) if num%3 == 0])
生成器表达式
laomuji = ('egg%d'%i for i in range(10)) #用小括号是生成器表达式
print(laomuji)
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
print((name for lst in names for name in lst if name.count('e') >= 2)) #是一个生成器
for i in (name for lst in names for name in lst if name.count('e') >= 2):
print(i)
三种方法从生成器中取值
#1.a.__next__()
#2.for
for i in laomuji:
print(i)
#3.list强转
print(list(a))
字典推导式
mcase = {'a':10,'b':34}
new_dic = {mcase[k]:k for k in mcase} #建和值对调
print(new_dic)
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
# {a:17,b:34,z:3} #键变小写,值相加
new_dic = {k.lower():mcase.get(k.lower(),0)+mcase.get(k.upper(),0) for k in mcase}
print(new_dic)
集合推导式
l = [-1,1,2,3,4,5]
print([i*i for i in l]) #列表推导式不能去重
print({i*i for i in l}) #集合推导式能去重
# 列表推导式[] - 生成器表达式()
# 尽量让推导式简化你的操作,增强代码的可读性
# 如果推导式过于复杂了,应该转换成普通的python代码
# 所有的列表推导式都可以转换成生成器表达式,并且应该在代码中尽可能多使用生成器表达式而不是列表推导式
#在代码里 多层嵌套的for循环是禁忌 —— 会大幅度增加代码的复杂度
既然选择了远方,便是风雨兼程...