python基础之协程函数、列表表达式、生成器表达式
一、协程函数
协程函数的定义?
如果在一个函数内部yield的使用方式是表达式形式的话,如x=yield,那么该函数称为协程函数
协程函数补充:
def init(func): def wrapper(*args,**kwargs): res=func(*args,**kwargs) next(res) return res return wrapper @init #eater=init(eater) def eater(name): print('%s start to eat' % name) food_list=[] while True: food = yield food_list print('%s eat %s' % (name, food)) food_list.append(food) e = eater('luchuan') #wrapper('luchuan') # print(e) # next(e) #e.send(None) print(e.send('123')) print(e.send('123')) print(e.send('123')) print(e.send('123')) print(e.send('123'))
协程函数的应用?
递归文件夹及子文件夹中的文件,把有'python'参数的文件绝对路径打印出来:
#grep -rl 'python' C:\luchuan
import os,time def init(func): #装饰器next() def wrapper(*args,**kwargs): res=func(*args,**kwargs) next(res) return res return wrapper @init def search(target): '找到文件的绝对路径' while True: dir_name=yield print('车间search开始生产产品:文件的绝对路径') time.sleep(0.2) g=os.walk(dir_name) for i in g: for j in i[-1]: file_path = '%s\\%s' % (i[0],j) target.send(file_path) @init def opener(target): '打开文件,获取文件句柄' while True: file_path=yield print('车间opener开始生产产品:文件句柄') time.sleep(0.2) with open(file_path) as f: target.send((file_path,f)) @init def cat(target): '读取文件内容' while True: file_path,f=yield print('车间cat开始生产产品:文件的一行内容') time.sleep(0.2) for line in f: target.send((file_path,line)) @init def grep(pattern,target): while True: file_path,line=yield print('车间grep开始生产产品:包含python这一行内容的文件路径') time.sleep(0.2) if pattern in line: target.send(file_path) @init def printer(): while True: file_path=yield print('车间printer开始生产产品:得到最终的产品') time.sleep(0.2) print(file_path) g=search(opener(cat(grep('python',printer())))) g.send("C:\\luchuan") # g.send("C:\\lulu") #也可以传其他路径
os.walk()方法用于通过在目录树中游走输出在目录中的文件名,向上或者向下。
在Unix,Windows中有效。
import os g=os.walk('C:\\luchuan') #遍历所有luchuan路径下的文件绝对路径 for i in g: # print(i) for j in i[-1]: file_path='%s\\%s' %(i[0],j) print(file_path)
二、面向过程编程
以上协程函数应用就是面向过程编程。
面向过程的编程思想:流水线式的编程思想,在设计程序时,需要把整个流程设计出来。
优点:
- 体系结构更加清晰
- 简化程序的复杂度
缺点:
- 可扩展性极其的差,所以说面向过程的应用场景是:不需要经常变化的软件,如:linux内核,httpd,git等软件。
三、列表解析
声明式编程:列表解析、生成器表达式都是声明式编程,就跟声明变量一样。
三元表达式:
三元运算时if-else语句的快捷操作,也被称为条件运算。可以让你的代码更加紧凑,更加美观。
[on_true] if [expression] else [on_false]
x, y = 50, 25 small = x if x < y else y
列表解析初识:
egg_list=[] for i in range(100): #for循环表示 egg_list.append('egg%s' %i) print(egg_list) l=[ 'egg%s' %i for i in range(100) ] #列表表达式表示 print(l)
复杂的列表解析:
#应用1: l=[1,2,3,4] s='hello' l1=[] for num in l: for s1 in s: t=(num,s1) l1.append(t) print(l1) l1=[ (num,s1) for num in l if num > 2 for s1 in s ] print(l1) #应用2: import os g=os.walk('C:\\luchuan') file_path_list=[] for i in g: # print(i) for j in i[-1]: file_path_list.append('%s\\%s' %(i[0],j)) print(file_path_list) g=os.walk('C:\\luchuan') l1=['%s\\%s' %(i[0],j) for i in g for j in i[-1]] print(l1)
四、生成器表达式
把列表解析的[]换成()得到的就是生成器表达式,语法和列表解析一样。
生成器表达式初识:
l=['egg%s' %i for i in range(100)] print(l) g=l=('egg%s' %i for i in range(1000000000000000000000)) # print(g) # print(next(g)) # print(next(g)) for i in g: print(i)
生成器表达式扩展:
# 应用1: f=open('a.txt') l=[] for line in f: line=line.strip() l.append(line) print(l) f.seek(0) l1=[line.strip() for line in f] print(l1) f.seek(0) g=(line.strip() for line in f) print(g) print(next(g)) f=open('a.txt') g=(line.strip() for line in f) l=list(g) print(l) # 应用2: nums_g = (i for i in range(3)) print(sum(nums_g)) print(sum([1,2,3,4])) # 应用3: money_l=[] with open('b.txt') as f: for line in f: goods=line.split() res=float(goods[-1])*float(goods[-2]) money_l.append(res) print(money_l) f=open('b.txt') # 推荐使用这种方式写代码 g=(float(line.split()[-1])*float(line.split()[-2]) for line in f) print(sum(g)) with open('b.txt') as f: # 不建议使用这种方式,代码不易观察 print(sum((float(line.split()[-1])*float(line.split()[-2]) for line in f))) # 应用4: res=[] with open('b.txt') as f: for line in f: # print(line) l=line.split() # print(l) d={} d['name']=l[0] d['price']=l[1] d['count']=l[2] res.append(d) print(res) #取出单价>10000 with open('b.txt') as f: res=(line.split() for line in f) # print(res) dic_g=({'name':i[0],'price':i[1],'count':i[2]} for i in res if float(i[1]) > 10000) # print(dic_g) print(list(dic_g))
asdfasdfasdfasdfasdf 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 123123123123 asdfasdfasdfasdf
apple 10 3 banana 5 10 tesla 1000000.3 1 lenovo 10000 3
总结:
总结:
1、把列表解析的[]换成()得到的就是生成器表达式
2、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3、python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如,sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:
num=sum(x ** 2 for x in range(4))
而不用多此一举的先构造一个列表:
num=sum([x ** 2 for x in range(4)])
练习题:
习题一:
有两个列表,分别存放来老男孩报名学习linux和python课程的学生名字
linux=['钢弹','小壁虎','小虎比','alex','wupeiqi','yuanhao']
python=['dragon','钢弹','zhejiangF4','小虎比']
问题一:得出既报名linux又报名python的学生列表
L=[] for i in linux: for j in python: if i == j: L.append(i) print(L) lp=[i for i in linux for j in python if i==j ] print(lp)
问题二:得出只报名linux,而没有报名python的学生列表
L=[] for i in linux: if i not in python: L.append(i) print(L) lp=[i for i in linux if i not in python ] print(lp)
问题三:得出只报名python,而没有报名linux的学生列表
L = [] for j in python: if j not in linux: L.append(j) print(L) lp=[ j for j in python if j not in linux ] print(lp)
习题二:
shares={
'IBM':36.6,
'lenovo':27.3,
'huawei':40.3,
'oldboy':3.2,
'ocean':20.1
}
问题一:得出股票价格大于30的股票名字列表
L=[] for i in shares: print(i,shares[i]) if shares[i] > 30: L.append(i) print(L) lp = [i for i in shares if shares[i] > 30] print(lp)
问题二:求出所有股票的总价格
L=[] for i in shares: L.append(shares[i]) print(sum(L)) num=sum(shares[i] for i in shares) print(num)
习题三:
l=[10,2,3,4,5,6,7]
得到一个新列表l1,新列表中每个元素是l中对应每个元素值的平方
l1=[] for i in l: l1.append(i**2) print(l1) lp=[i**2 for i in l] print(lp)
过滤出l1中大于40的值,然后求和
l1=[] for i in l: if i**2 > 40: l1.append(i**2) print(sum(l1)) lp=sum(i**2 for i in l if i**2 > 40) print(lp)