一、协程函数
yield的用法:
1:把函数的执行结果封装好__iter__和__next__,即得到一个迭代器
2:与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yield可以返回多次值
3:函数暂停与再继续运行的状态是有yield保存
1 # 例子1
2 # def chi(name):
3 # print('%s 开始上菜啦~'%name)
4 # cd=[] #菜单
5 # while True:
6 # food=yield cd
7 # cd.append(food)
8 # print('%s上了一份%s'%(name,food))
9 # print(cd)
10 # esa=chi('alex')
11 # esa.send('芹菜')
12 # 例子2
13 # def chi(name):
14 # print('%s 开始上菜啦~'%name)
15 # cd=[] #菜单
16 # while True:
17 # food=yield cd
18 # cd.append(food)
19 # print('%s上了一份%s'%(name,food))
20 # def shui():
21 # name = input('服务员名字>>: ').strip()
22 # while True:
23 # food=input('菜名>>: ').strip()
24 # sc=chi(name)
25 # next(sc)#初始化:就是让函数执行停到yield
26 # if not food or not name :continue
27 # sc.send(food)#给yield传值
28 # shui()
例子
通过装饰器初始化:
1 def chushi(func):
2 def hua(*args,**kwargs):
3 g=func(*args,**kwargs)
4 next(g)
5 return g
6 return hua
7 @chushi
8 def chi(name):
9 print('%s 开始上菜啦~'%name)
10 cd=[] #菜单
11 while True:
12 food=yield cd
13 cd.append(food)
14 print('%s上了一份%s'%(name,food))
15 print(cd)
16 esa=chi('alex')
17 esa.send('芹菜')
18
19
20
21 #例子2
22 # def chushi(func):
23 # def hua(*args,**kwargs):
24 # g=func(*args,**kwargs)
25 # next(g)
26 # return g
27 # return hua
28 # @chushi
29 # def chi(name):
30 # print('%s 开始上菜啦~'%name)
31 # cd=[] #菜单
32 # while True:
33 # food=yield cd
34 # cd.append(food)
35 # print('%s上了一份%s'%(name,food))
36 # def shui():
37 # name = input('服务员名字>>: ').strip()
38 # while True:
39 # food=input('菜名>>: ').strip()
40 # sc=chi(name)
41 # # next(sc)#初始化:就是让函数执行停到yield
42 # if not food or not name :continue
43 # sc.send(food)#给yield传值
44 # shui()
例子
二、面向过程编程
面向过程:核心是过程二字,过程即解决问题的步骤,基于面向过程去设计程序就像是在设计
一条工业流水线,是一种机械式的思维方式
优点:程序结构清晰,可以把复杂的问题简单化,流程化
缺点:可扩展性差,一条流线只是用来解决一个问题
应用场景:linux内核,git,httpd,shell脚本
1 import os
2 def init(func):
3 def wrapper(*args,**kwargs):
4 g=func(*args,**kwargs)
5 next(g)
6 return g
7 return wrapper
8
9 #第一阶段:找到所有文件的绝对路径
10 @init
11 def search(target):
12 while True:
13 filepath=yield
14 g=os.walk(filepath)
15 for pardir,_,files in g:
16 for file in files:
17 abspath=r'%s\%s' %(pardir,file)
18 target.send(abspath)
19 # search(r'C:\Users\Administrator\PycharmProjects\python18期周末班\day5\aaa')
20 # g=search()
21 # g.send(r'C:\Python27')
22
23 #第二阶段:打开文件
24 @init
25 def opener(target):
26 while True:
27 abspath=yield
28 with open(abspath,'rb') as f:
29 target.send((abspath,f))
30
31
32
33
34 #第三阶段:循环读出每一行内容
35 @init
36 def cat(target):
37 while True:
38 abspath,f=yield #(abspath,f)
39 for line in f:
40 res=target.send((abspath,line))
41 if res:break
42
43
44
45 #第四阶段:过滤
46 @init
47 def grep(pattern,target):
48 tag=False
49 while True:
50 abspath,line=yield tag
51 tag=False
52 if pattern in line:
53 target.send(abspath)
54 tag=True
55
56
57 #第五阶段:打印该行属于的文件名
58 @init
59 def printer():
60 while True:
61 abspath=yield
62 print(abspath)
63
64 g = search(opener(cat(grep('os'.encode('utf-8'), printer()))))
65 # g.send(r'C:\Users\Administrator\PycharmProjects\python18期周末班\day5\aaa')
66
67 g.send(r'C:\Users\Administrator\PycharmProjects\python18期周末班')
68 #a1.txt,a2.txt,b1.txt
grep -rl 'error' /dir/
三、递归与二分法
递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身
1 #直接
2 # def func():
3 # print('from func')
4 # func()
5 #
6 # func()
7
8 #间接
9 # def foo():
10 # print('from foo')
11 # bar()
12 #
13 # def bar():
14 # print('from bar')
15 # foo()
16 #
17 # foo()
例子
递归的执行分为两个阶段:
1 递推
2 回溯
1 l =[1, 2, [3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15,[16,[17,]],19]]]]]]]
2
3 def search(l):
4 for item in l:
5 if type(item) is list:
6 search(item)
7 else:
8 print(item)
9
10 search(l)
例子
二分法
1 #例子1
2 l = [1,2,5,7,10,31,44,47,56,99,102,130,240]
3
4
5 def binary_search(l,num):
6 print(l) [10, 31]
7 if len(l) > 1:
8 mid_index=len(l)//2 1
9 if num > l[mid_index]:
10 in the right
11 l=l[mid_index:] l=[31]
12 binary_search(l,num)
13 elif num < l[mid_index]:
14 in the left
15 l=l[:mid_index]
16 binary_search(l,num)
17 else:
18 print('find it')
19 else:
20 if l[0] == num:
21 print('find it')
22 else:
23 print('not exist')
24 return
25
26 binary_search(l,32)
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 #例子2
45 l = [1,2,5,7,10,31,44,47,56,99,102,130,240]
46
47
48 def binary_search(l,num):
49 print(l)
50 if len(l) == 1:
51 if l[0] == num:
52 print('find it')
53 else:
54 print('not exists')
55 return
56 mid_index=len(l)//2
57 mid_value=l[mid_index]
58 if num == mid_value:
59 print('find it')
60 return
61 if num > mid_value:
62 l=l[mid_index:]
63 if num < mid_value:
64 l=l[:mid_index]
65 binary_search(l,num)
66
67 binary_search(l,32)
例子
四、模块与包
1.模块只在第一次导入时才会执行,之后的导入都是直接引用内存已经存在的结果
模块搜索路径:
内存中--》内置模块————》sys.path
注意:自定义的模块名一定不要与python自带的模块名重名
2.什么是模块
常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
但其实import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
3.import的导入
1 #spam.py
2 print('from the spam.py')
3
4 money=1000
5
6 def read1():
7 print('spam->read1->money',money)
8
9 def read2():
10 print('spam->read2 calling read')
11 read1()
12
13 def change():
14 global money
15 money=0
span.py
导入span模块
1 #test.py
2 import spam #只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次'from the spam.py',当然其他的顶级代码也都被执行了,只不过没有显示效果.
3 import spam
4 import spam
5 import spam
6 '''
7 执行结果:
8 from the spam.py
9 '''
例子
可以使用__all__来控制*(用来发布新版本)
在spam.py中新增一行
__all__=['money','read1'] #这样在另外一个文件中用from spam import *就这能导入列表中规定的两个名字
4.rom.......import的导入
优点:使用源文件内的名字时无需加前缀,使用方便
缺点:容易与当前文件的名称空间内的名字混淆
5.绝对导入和相对导入
1 在glance/api/version.py
2
3 #绝对导入
4 from glance.cmd import manage
5 manage.main()
6
7 #相对导入
8 from ..cmd import manage
9 manage.main()
例子
1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
强调:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块