一、协程函数  

 yield的用法:

1:把函数的执行结果封装好__iter__和__next__,即得到一个迭代器
2:与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yield可以返回多次值
3:函数暂停与再继续运行的状态是有yield保存


yield在python中的用法_python

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()


例子


  通过装饰器初始化:




yield在python中的用法_初始化_02

yield在python中的用法_python

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)


例子


  二分法

yield在python中的用法_python

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的导入




yield在python中的用法_初始化_02

yield在python中的用法_python

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. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块