1 协程函数

1.1 协程函数理解

协程函数就是使用了yield表达式形式的生成器

def eater(name):
print("%s eat food" %name)
while True:
food = yield
print("done") g = eater("gangdan")
print(g)

结果:

generator object eater at 0x00000000028DC048

这里就证明了g现在就是生成器函数

1. 2 协程函数赋值过程

用的是yield的表达式形式

要先运行next(),让函数初始化并停在yield,相当于初始化函数,然后再send() ,send会给yield传一个值

** next()和send() 都是让函数在上次暂停的位置继续运行,

next是让函数初始化

send在触发下一次代码的执行时,会给yield赋值

**

def eater(name):
print('%s start to eat food' %name)
food_list=[]
while True:
food=yield food_list
print('%s get %s ,to start eat' %(name,food))
food_list.append(food) e=eater('钢蛋') # wrapper('')
# print(e)
print(next(e)) # 现在是运行函数,让函数初始化
print(e.send('包子')) #
print(e.send('韭菜馅包子'))
print(e.send('大蒜包子'))

这里的关键是:

要先运行next()函数

用装饰器函数把next()函数先运行一次:

def start(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs) # next()
next(res) # 这是关键
return res
return wrapper @start # e = start(e)
def eater(name):
print('%s start to eat food' %name)
food_list=[]
while True:
food=yield food_list
print('%s get %s ,to start eat' %(name,food))
food_list.append(food) e=eater('钢蛋') # wrapper('钢蛋') print(e.send('包子'))
print(e.send('韭菜馅包子'))
print(e.send('大蒜包子'))

在@start # e = start(e) 后面写上,运行start函数,start函数返回wrapper

1.3 协程函数使用装饰器初始化

这里主要是为了防止忘记初始化next操作,在装饰器中添加

def init(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
next(res) # 在这里执行next
return res
return wrapper @init # eater=init(rater)
def eater(name):
print("%s eat food" %name)
food_list=[]
while True:
food = yield food_list
print("%s star to eat %s" %(name,food))
food_list.append(food)
print("done") g = eater("gangdan") # 这里就不需要next
print(g.send("1"))
print(g.send("2"))
print(g.send("3"))
print(g.send("4"))

结果:

gangdan eat food

gangdan star to eat 1

['1']

gangdan star to eat 2

['1', '2']

gangdan star to eat 3

['1', '2', '3']

gangdan star to eat 4

['1', '2', '3', '4']

只要用到装饰器函数,马上写装饰器函数,写@init马上想到**  eater=init(eater)   **,先执行装饰器函数。

**关键是**next(res),这里是是对生成器进行初始化。这里就会只执行一次,执行完后后面运行的都是e.send()

### 1.2 协程函数的应用 ###

过滤一个文件下的子文件、字文件夹的内容中的相应的内容,在Linux中的命令就是 *grep -rl 'python'  /etc*

使用了Python的包os 里面的walk(),能够把参数中的路径下的文件夹打开并返回一个元组
```python
>>> import os
>>> os.walk('D:\test')
generator object walk at 0x0000000002ADB3B8 >>> os.walk('D:\\test') # 以后使用这种路径方式,win下
>>> os.walk(r'D:\test') # 使用r 是让字符串中的符号没有特殊意义,针对的是转义

出现错误,是因为路径的原因,但是在不同的机器上有的是可以的

>>> g=os.walk('D:\test')
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

以后推荐是用\

>>> g=os.walk('D:\\test')
>>> next(g)
('D:\\test', ['a', 'b'], ['test.txt'])

返回的是一个元组第一个元素是文件的路径,第二个是文件夹,第三个是该路径下的文件

1.2.1 程序流程

  1. 找文件路径 --os.walk
  2. 然后打开文件 --open
  3. 读取文件的每一行内容 -- for line in f
  4. 过滤一行内容中是否有Python if 'python' in line
  5. 打印包含Python的文件路径

程序是从上往下执行的,1产生的路径作为参数给2,2产生的给3...

上面产生的结果是下面的输入参数

1 找文件的路径

g是一个生成器,就能够用next()执行,每次next就是运行一次,这里的运行结果是依次打开文件的路径

>>> g=os.walk('D:\\test')
>>> next(g)
('D:\\test', ['a', 'b'], ['test.txt'])
>>> next(g)
('D:\\test\\a', ['a1'], ['a.txt'])
>>> next(g)
('D:\\test\\a\\a1', [], ['a1.txt'])
>>> next(g)
('D:\\test\\b', ['b1'], ['b.txt'])
>>> next(g)
('D:\\test\\b\\b1', [], ['b1.txt'])

我们在打开文件的时候需要找到文件的绝对路径,现在可以通过字符串拼接的方法把第一部分和第三部分进行拼接

用循环打开:

import os
# def serach():
g = os.walk('D:\\test')
for i in g:
print(i)

结果:

('D:\test', ['a', 'b'], ['test.txt'])

('D:\test\a', ['a1'], ['a.txt'])

('D:\test\a\a1', [], ['a1.txt'])

('D:\test\b', ['b1'], ['b.txt'])

('D:\test\b\b1', [], ['b1.txt'])

将查询出来的文件和路径进行拼接,拼接成绝对路径

import os
# def serach():
g = os.walk('D:\\test')
for i in g:
# print(i)
for j in i[-1]: # 对最后一个元素进行遍历,这些都是文件
file_path= '%s\\%s' %(i[0],j)
print(file_path)

结果:

D:\test\test.txt

D:\test\a\a.txt

D:\test\a\a1\a1.txt

D:\test\b\b.txt

D:\test\b\b1\b1.txt

这样就把文件的所有的绝对路径找出来了

用函数实现:

def search():
while True:
file_name = yield # 通过white循环能够循环接收
g = os.walk(file_name) # 这里就换成了参数
for i in g:
for j in i[-1]: # 对最后一个元素进行遍历,这些都是文件
file_path= '%s\\%s' %(i[0],j)
print(file_path) g=search() # g就是生成器函数
next(g) # 初始化
g.send('D:\\test') # 通过send传递的是路径

2 然后打开文件

写程序中,在这里遇到的问题是 with open(file_path) as f: AttributeError: enter,不明白是为什么,然后想到open可能是系统已经用了的,所以修改名字后执行成功。

@init   # 初始化生成器
def opener(target):
"打开文件,操作句柄"
while True:
file_path=yield #  接收search传递的路径
with open(file_path) as f:
target.send((file_path,f)) # send多个用元组的方式,为了把文件的路径传递下去

3 读取文件的每一行内容

@init
def cat(target):
while True:
file_path,f=yield
for line in f:
target.send((file_path,line)) # 同时传递文件路径和每一行的内容

4 过滤一行内容中是否有

@init
def grep(pattern,target): # patter是过滤的参数
while True:
file_path,line=yield
if pattern in line:
target.send(file_path) # 传递有相应内容的文件路径

5 打印包含Python的文件路径

@init
def printer():
while True:
file_path=yield
print(file_path)

上面的是函数的定义阶段,下面是函数的执行阶段:

g=search(opener(cat(grep('python',printer()))))
g.send('D:\\test')

target这个生成器:

opener(cat(grep('python',printer())))

对此的理解:

关于target还是有个点没有想明白,是target的传递的情况,我知道是从下面往上传递的。不明白的中怎么会这样接收,它的起始点在哪里

面向过程的编程思想:流水线式的编程思想,在设计程序时,需要把整个流程设计出来

优点:

1:体系结构更加清晰

2:简化程序的复杂度

缺点:

1:可扩展性极其的差,所以说面向过程的应用场景是:不需要经常变化的软件,如:linux内核,httpd,git等软件

Python协程函数的更多相关文章

  1. python协程函数、递归、匿名函数与内置函数使用、模块与包

    目录: 协程函数(yield生成器用法二) 面向过程编程 递归 匿名函数与内置函数的使用 模块 包 常用标准模块之re(正则表达式) 一.协程函数(yield生成器用法二) 1.生成器的语句形式 a. ...

  2. python协程函数应用 列表生成式 生成器表达式

    协程函数应用 列表生成式 生成器表达式   一.知识点整理: 1.可迭代的:对象下有_iter_方法的都是可迭代的对象 迭代器:对象._iter_()得到的结果就是迭代器 迭代器的特性: 迭代器._n ...

  3. Python基础(协程函数、内置函数、递归、模块和包)-day05

    写在前面 上课第五天,打卡: 凭着爱,再回首: 一.协程函数(生成器:yield的表达式形式) 1.yield 的语句形式: yield 1 - 这种方式在 Python基础(函数部分)-day04  ...

  4. python之协程函数、递归、二分法

    一.协程函数: 协程函数的语法: def eater(name): print('%s说:我开动啦' %name) food_list=[] while True: food=yield food_l ...

  5. python基础之协程函数、列表表达式、生成器表达式

    一.协程函数 协程函数的定义?如果在一个函数内部yield的使用方式是表达式形式的话,如x=yield,那么该函数称为协程函数 协程函数补充: def init(func): def wrapper( ...

  6. python基础----迭代器、生成器、协程函数及应用(面向过程实例)

    一.什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2.可迭代 ...

  7. Py修行路 python基础 (十二) 协程函数应用 列表生成式 生成器表达式

    一.知识点整理: 1.可迭代的:对象下有_iter_方法的都是可迭代的对象 迭代器:对象._iter_()得到的结果就是迭代器 迭代器的特性: 迭代器._next_() 取下一个值 优点: 1.提供了 ...

  8. python基础-协程函数、递归、模块、包等内容

    1. 协程函数 1.1 yield基本用法 yield作用 1.把函数的执行结果封装好,即封装__iter__和__next__,即得到一个迭代器 2.与return功能类似,都可以返回值,但不同的是 ...

  9. python 3 协程函数

    python 3 协程函数 1:把函数的执行结果封装好__iter__和__next__,即得到一个迭代器 2:与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yiel ...

随机推荐

  1. 聊聊Java里常用的并发集合

    前言 在我们的程序开发过程中,如果涉及到多线程环境,那么对于集合框架的使用就必须更加谨慎了,因为大部分的集合类在不施加额外控制的情况下直接在并发环境中直接使用可能会出现数据不一致的问题,所以为了解决这 ...

  2. HihoCoder 1121二分图一•二分图判定

    背景: 个名字,表示这两个人有一场相亲.由于姑姑年龄比较大了记性不是太好,加上相亲的人很多,所以姑姑一时也想不起来其中有些人的性别.因此她拜托我检查一下相亲表里面有没有错误的记录,即是否把两个同性安排 ...

  3. Unity NGUI学习

    环境 Unity4.3    NGUI v3.68 导入 Project界面->右键->import package->custom package载入安装包即可 untiy4.6用 ...

  4. PUSH 和 远程推送

    1. UIApplacation向 APNS 注册 push notification 服务 (1) 应用程序要支持推送服务, 在网页里面配置  http://developer.apple.com/ ...

  5. AFN的使用

    http网络库是集XML解析,Json解析,网络图片下载,plist解析,数据流请求操作,上传,下载,缓存等网络众多功能于一身的强大的类库.最新版本支持session,xctool单元测试.网络获取数 ...

  6. iOS开发 - CocoaPods的常见使用方式

    1 CocoaPods 的安装 1.1 作用: 帮助管理和维护第三方框架,快速的搜索到第三方框架, 然后自动集成到工程里面来, 并编译成一个libPod.a的静态库给我们项目用 1.2 理解:  1. ...

  7. idea | SpringBoot项目热加载

    第一步: 在pom文件添加依赖: <dependency> <groupId>org.springframework.boot</groupId> <arti ...

  8. djangoForm组件

    https://www.cnblogs.com/jabbok/p/9273786.html 在之前学习了html form信息传递到django,然后进行处理,但是这很不方便. django有自己的组 ...

  9. 爬虫的UA池和代理池

    爬虫的UA池和代理池   一.下载中间件 先祭出框架图: 下载中间件(Downloader Middlewares) 位于scrapy引擎和下载器之间的一层组件. - 作用: (1)引擎将请求传递给下 ...

  10. 【模板】平衡树——Treap和Splay

    二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值.且左右子树也分别是二叉搜索树.(如下) $BST$的作用:维护一个有序数列,支持插入$x$ ...