生成器进阶
一、生成器调用 send()的使用方法:
先next在send()
#一周利率转换 def average_func(): total = 0 count = 0 avweage = 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.__next__()) #0 print(g.send(30)) #30 print(g.send(20)) #30
从上面可以的生成器调用可以看出:
1、send和next动作的起止位置是完全相同的
2、send可以把一个值作为信号量传递到函数中去
3、在生成器执行伊始,只能先用next
4、只要要用send传递参数的时候,必须在生成器中海油一个未被返回的yield
以上是对send调用的总结
二、列表推导式和生成器表达式:
1、列表推导式:
列表推导式也叫列表表达式,是人们最长用的,主要功能是简化代码.例如:
[1,3,5] ==[1,9,25] #正常书写: 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]])
练习:
[0,2,4,6] == [0,1,2,3] print([i//2 for i in range(0,7,2)]) #两个/是为了取整数
l = [{'name':'alex','age':80},{'name':'egon','age':40},{'name':'yuan','age':30},{'name':'nezha','age':18}] #取所有名字 print([i['name'] for i in l]) #取出大于18岁的名字 print([i['name'] for i in l if i['age'] > 18]) #30以内所有能被3整除的数: print[(num for num in range(31) if num%3==0]) #30以内所有能被3整除的平方: print([num*num for num in range(31) if num%3==0])
#取e 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])
字典推导式:
例一:将一个字典的key和value对调
mcase = {'a': 10, 'b': 34} mcase_frequency = {mcase[k]: k for k in mcase} print(mcase_frequency)
例二:合并大小写对应的value值,将k统一成小写
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()} print(mcase_frequency
集合推导式
例:计算列表中每个值的平方,自带去重功能
squared = {x**2 for x in [1, -1, 2]} print(squared) # Output: set([1, 4])
2、生成器Generator:
本质:迭代器,所以拥有__iter__方法和__next__方法
特点:惰性运算,开发者自定义
使用生成器的优点:
1)延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。
#列表解析 sum([i for i in range(100000000)])#内存占用大,机器容易卡死 #生成器表达式 sum(i for i in range(100000000))#几乎不占内存
2).提高代码可读性
总结:
生成器表达式:—节省内存,简化代码
最常用的是:列表推导式 生成器表达式
尽量让推导式简化你的操作,增强代码的可读性
如果推导式过于复杂了,应该转换成普通的Python代码
所有的列表推导式都可以转换成生成器表达式,并且应该在代码中尽可能多使用生成器表达而不是列表推导式
在代码中 多层嵌套的for循环是禁忌--会大幅度增加代码的复杂度