协程函数
面向过程编程
递归与二分法
内置函数 lambda
模块与包的使用
import
from ... import ...
常用模块
##################################
函数中只要有yield , 函数执行的结果就变成了一个生成器
他并不会马上执行
生成器本身就是一个迭代器,使用next() 触发函数的执行
yield功能
1、把函数的执行结果封装好__iter__和__next__,得到一个迭代器
2、与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yield可以返回多次值
3、函数暂停与再继续运行的状态是有yield保存
1 # 2 def func(count): 3 print('start') 4 while True: 5 yield count 6 count+=1 7 8 g=func(10) 9 # print(g) 10 print(next(g)) 11 12 print(next(g))
yield的表达式形式的应用
吃饭的过程,三种方法:
1 #yield的表达式形式的应用 2 #吃饭的过程 3 ##方法一: 4 def eater(name): 5 print('%s 说:我要开始吃东西啦!' %name) 6 food_list = [] #定义一个菜单空列表 7 while True: 8 # food=yield #yield 没有返回值,后面需要给yield赋值,只要函数中有yield关键字,函数执行的结果就是一个生成器 9 food=yield food_list #返回值 菜单列表 10 food_list.append(food) #往列表中添加值 11 print('%s eat %s !' %(name,food)) 12 13 alex_g=eater('alex') #函数要执行下,才能得到一个生成器 14 # print(alex_g) #是个生成器 <generator object eater at 0x0000000006B522B0> 15 16 # print(next(alex_g)) #执行结果 None 17 # print('==============>') 18 # print(next(alex_g)) #执行结果 alex eat None , food没有接收到值 ,所以每次都要给food传一个值,通过yield取值赋值给food 19 # print('==============>') 20 # print(next(alex_g)) 21 #第一阶段 初始化 next() 生成器刚开始的时候,必须给一个None值 22 next(alex_g) #保证在初始的位置,简单的触发生成器的执行,保证函数停在yield位置 等同于 alex_g.send(None) 23 print('==========>') 24 25 #第二阶段 给yield传值 通过alex_g.send() 发送值 26 alex_g.send('包子') #发送值 先给当前暂停位置的yield传值 , 执行结果为: alex eat 包子 27 #继续往下执行,直到再次碰到yield,然后暂停,并且把yield后的返回值当做本次调用的返回值 28 # alex_g.send('八宝粥') #发送值 29 print(alex_g.send('八宝粥')) 30 print(alex_g.send('煎饺'))
1 ##方法二: 2 ##修改第二阶段 3 4 def eater(name): 5 print('%s 说:我要开始吃东西啦!' %name) 6 food_list = [] #定义一个菜单空列表 7 while True: 8 food=yield food_list #返回值 菜单列表 9 food_list.append(food) #往列表中添加值 10 print('%s eat %s !' %(name,food)) 11 12 alex_g=eater('alex') #函数要执行下,才能得到一个生成器 13 14 next(alex_g) 15 print('==========>') 16 17 ##第二阶段传值的功能写成一个交互函数 18 19 def producer(): 20 alex_g=eater('alex') 21 #第一阶段:初始化 22 next(alex_g) 23 #第二阶段:给yield传值 24 while True: 25 food=input('>>: ').strip() 26 if not food:continue 27 print(alex_g.send(food)) 28 29 30 producer() 31 ##############################
1 ##方法三: 2 3 #不容易记得初始化 4 #用装饰器解决初始化问题 5 ####装饰器基本形式 6 ''' 7 def init(func): 8 def wrapper(*args, **kwargs): 9 pass 10 return wrapper 11 ''' 12 ##先写个什么都没干的装饰器 13 ''' 14 def init(func): 15 def wrapper(*args, **kwargs): 16 g = func(*args, **kwargs) 17 return g 18 return wrapper 19 ''' 20 #完成调用初始化工作 21 def init(func): 22 def wrapper(*args, **kwargs): 23 g = func(*args, **kwargs) 24 next(g) #调用next()初始化 25 return g 26 return wrapper 27 @init #将装饰器加在目录函数上 28 def eater(name): 29 print('%s 说:我要开始吃东西啦!' %name) 30 food_list = [] #定义一个菜单空列表 31 while True: 32 # food=yield #yield 没有返回值,后面需要给yield赋值,只要函数中有yield关键字,函数执行的结果就是一个生成器 33 food=yield food_list #返回值 菜单列表 34 food_list.append(food) #往列表中添加值 35 print('%s eat %s !' %(name,food)) 36 37 alex_g=eater('alex') 38 alex_g.send('包子') 39 print(alex_g.send('八宝粥')) 40 print(alex_g.send('煎饺'))
面向过程
面向过程:核心是过程二字,明确的区分几个阶段,
基于面向过程去设计程序就像是在设计一条工业流水线,是一种机械式的思维方式
过程即解决问题的步骤
写程序要先设计
优点:程序结构清晰,可以把负责的问题简单化,流程化
缺点:可扩展性差,一条流水线只是用来解决一个问题
应用场景:Linux内核, Git, httpd, shell脚本
1 ##遍历目录下的所有文件 2 #三种方式 3 #一、普通方式: 4 import os #导入os模块,os下面有个walk模块,他是个生成器 5 import time 6 7 #第一阶段:找到所有文件的绝对路径 8 #使用os.walk()的方法,将walk生成的元组里的元素拼接成绝对路径 9 def search(filepath): 10 g=os.walk(filepath) 11 for pardir,_,files in g: 12 for file in files: 13 abspath = r'%s\%s' %(pardir,file) 14 print(abspath) 15 fp = input('请输入目录绝对路径:') 16 search(r'%s' % (fp)) 17 time.sleep(10) 18 19 ##二、装饰器方式,手动初始化装饰器 20 import os #导入os模块,os下面有个walk模块,他是个生成器 21 import time 22 23 #第一阶段:找到所有文件的绝对路径 24 #使用os.walk()的方法,将walk生成的元组里的元素拼接成绝对路径 25 def search(): 26 while True: 27 filepath = yield 28 g=os.walk(filepath) 29 for pardir,_,files in g: 30 for file in files: 31 abspath = r'%s\%s' %(pardir,file) 32 print(abspath) 33 34 fp = input('请输入目录绝对路径:') 35 g = search() #使用装饰器,要先初始化 36 next(g) #初始化 37 38 g.send(r'%s' % (fp)) 39 time.sleep(10) 40 41 ##三、自动初始化装饰器 42 import os #导入os模块,os下面有个walk模块,他是个生成器 43 import time 44 45 def init(func): #解决初始化问题 46 def wrapper(*args,**kwargs): 47 g=func(*args,**kwargs) 48 next(g) 49 return g 50 return wrapper 51 @init 52 #第一阶段:找到所有文件的绝对路径 53 #使用os.walk()的方法,将walk生成的元组里的元素拼接成绝对路径 54 def search(): 55 while True: 56 filepath = yield 57 g=os.walk(filepath) 58 for pardir,_,files in g: 59 for file in files: 60 abspath = r'%s\%s' %(pardir,file) 61 print(abspath) 62 # g = search('Null') 63 # next(g) 64 fp = input('请输入目录绝对路径:') 65 66 g = search() #使用装饰器,要先初始化 67 # next(g) #初始化 68 g.send(r'%s' % (fp)) 69 time.sleep(10)
1 #面向过程:核心是过程二字 2 #过程即解决问题的步骤 3 #写程序要先设计 4 5 6 #grep -rl 'error' /dir/ 7 #-r是递归着找,-l 是系列出文件名 ,找出目录下的所有文件,打开文件,找出有 error 的关键字,列出包含error的行的文件名 8 #思路:找出所有文件的绝对路径、打开文件、循环逐行读取每行文件内容、判断error是否在文件里(过滤)、打印改行属于的文件名 9 import os #导入os模块,os下面有个walk模块,他是个生成器 10 def init(func): #写一个装饰器,完成调用初始化工作 11 def wrapper(*args,**kwargs): 12 g=func(*args,**kwargs) 13 next(g) 14 return g 15 return wrapper 16 17 #第一阶段:找到所有文件的绝对路径 18 #使用os.walk()的方法,将walk生成的元组里的元素拼接成绝对路径 19 def search(filepath): 20 g=os.walk(filepath) 21 for parddir,_,file in g: 22 for file in files: 23 abspath = r'%S\%s' %(pardir,file) 24 print(abspath) 25 search(r'F:study18期') 26 @init 27 def search(target): #定义一个找路径的功能 28 while True: 29 filepath=yield 30 g=os.walk(filepath) #生成器,使用next()方法,可以读取该文件的路径、目录、文件名,并将其为元素组成一个元组。 31 for pardir,_,files in g: 32 for file in files: 33 abspath=r'%s\%s' %(pardir,file) 34 target.send(abspath) 35 # search(r'C:UsersAdministratorPycharmProjectspython123day5aaa') 36 # g=search() 37 # g.send(r'C:Python27') 38 39 #第二阶段:打开文件 40 @init 41 def opener(target): 42 while True: 43 abspath=yield 44 with open(abspath,'rb') as f: 45 target.send((abspath,f)) 46 47 48 49 50 #第三阶段:循环读出每一行内容 51 @init 52 def cat(target): 53 while True: 54 abspath,f=yield #(abspath,f) 55 for line in f: 56 res=target.send((abspath,line)) 57 if res:break 58 59 60 61 #第四阶段:过滤 62 @init 63 def grep(pattern,target): 64 tag=False 65 while True: 66 abspath,line=yield tag 67 tag=False 68 if pattern in line: 69 target.send(abspath) 70 tag=True 71 72 73 #第五阶段:打印该行属于的文件名 74 @init 75 def printer(): 76 while True: 77 abspath=yield 78 print(abspath) 79 80 g = search(opener(cat(grep('os'.encode('utf-8'), printer())))) 81 # g.send(r'C:UsersAdministratorPycharmProjectspython123day5aaa') 82 83 g.send(r'C:UsersAdministratorPycharmProjectspython234') 84 #a1.txt,a2.txt,b1.txt
#递归
'''
递归调用:再调用一个函数的过程中,直接或间接的调用了函数本身
python中递归的效率不高
记录下一次递归,保留上一次递归的状态,python对递归层级做了限制,默认1000层
程序中必须有个明确的结束条件
1 直接调用: 2 #直接 3 # def func(): 4 # print('from func') 5 # func() 6 # 7 # func() #直接 8 9 #间接 10 # def foo(): 11 # print('from foo') 12 # bar() 13 # 14 # def bar(): 15 # print('from bar') 16 # foo() 17 # 18 # foo() #间接调用
迭代 每一次更新都是上一次更新的结果
递归 直接或间接的调用了函数本身
递归包含两个阶段
递推:一层层的往下
回溯:一层层的回溯
什么时候用递归:
递归就是个循环的过程,递归可以做的,循环可以也可以做,只是麻烦点
循环是要明确的知道循环多少次
递归不需要
1 2 #取出列表中的所有元素 3 #若果使用循环,没法判断循环多少次,这里用递归来取值 4 5 list1 =[1, 2, [3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15,[16,[17,]],19]]]]]]] #有很多层 6 7 8 def search(l): #定义功能,给一个l参数 9 for i in l: #循环列表l中的元素 10 if type(i) is list: #判断如果元素是个列表 11 search(i) #重复该功能,继续查找元素 12 else: 13 print(i) #打印该元素 14 15 search(list1) #调用该功能 16 #
二分法
##二分法(把一组元素一半一半的一直分下去) #在下列列表中,搜索某个值是否存在,若存在请提示"find it!" , 除了in,如何遍历,使用二分法遍历 #若搜索的是不存在的,则返回“no exist!” l = [1,2,5,7,10,31,44,47,56,99,102,130,240,332,346.480,520,527,572,666,668,888,999] #从小到大排列(假设列表有很多值), def binary_search(l,num): print(l) #[10, 31] if len(l) > 1: mid_index=len(l)//2 #1 #把列表切一半 if num > l[mid_index]: #和中间的值比较,如果比中间值大,则要去右边找,就要切分 #in the right l=l[mid_index:] #l=[31] binary_search(l,num) elif num < l[mid_index]: #in the left l=l[:mid_index] binary_search(l,num) else: print('find it') else: if l[0] == num: print('find it') else: print('not exist!') return binary_search(l,888) ####结果 [1, 2, 5, 7, 10, 31, 44, 47, 56, 99, 102, 130, 240, 332, 346.48, 520, 527, 572, 666, 668, 888, 999] [1, 2, 5, 7, 10, 31, 44, 47, 56, 99, 102] [1, 2, 5, 7, 10] [5, 7, 10] [7, 10] [7] not exist!