yield表达式形式
首先了解
1.iterator
iterator叫做迭代器,用来遍历可以序列化的数据,比如一个list,set 等,当然如果对象想要能够使用迭代器来遍历,只要在该对象的类中添加__iter__()方法,该方法返回一个迭代器对象,迭代器对象中需要实现next()方法
for example:
>>> class sequenceClass(object): ... def __init__(self, *args): ... self._data = list(args) ... def __iter__(self): ... return DataIter(self) ... >>> class DataIter(object): ... def __init__(self, data): ... self._index = 0 ... self._data = data._data ... def next(self): ... if self._index >= len(self._data): raise StopIteration() ... d = self._data[self._index] ... self._index += 1 ... return d ... >>> data = sequenceClass(1,2,3,4) >>> for x in data: print x ... 1 2 3 4
执行方法如下:
创建对象data : data = sequenceClass(1,2,3,4)
使用for循环遍历data:
1.第一次for循环遍历data时,调用了data的__iter__()方法,该方法返回一个迭代器对象:DataIter
2.接着for循环每次调用DataIter对象的next()方法,next()方法返回数据
3.等到数据遍历完成时,抛出异常StopIteration, 该异常被for循环扑获,遍历结束。
以上是iterator的实现方法,但有一种更加简单的方式,但初学时可能不太好理解,就是使用yield表达式来遍历对象。
2.yield表达式及genetator
Python中,凡是含有yield的函数,被调用时都返回一个generator对象。generator设计的目的是能够更加简单的实现迭代器协议,例如上面的例子,需要单独写一个类来遍历数据,而用generator,直接一个yield表达式就可以用做迭代器了
>>> def test_generator(): ... s = 0 ... for i in xrange(10): ... s = yield i * s ... print 'i:', i ... print 's:', s ... print 'i * s', i * s ... >>> t = test_generator() >>> t <generator object test_generator at 0x10403a820> >>> >>> t.next() 0 >>> t.send(10) i: 0 s: 10 i * s 0 10 >>> t.send(11) i: 1 s: 11 i * s 11 22
执行方法如下:
1.定义了一个函数叫做test_generator
2.调用test_generator,得到t对象
3.运行t时,是一个generator对象
4.t.next()或者t.send(None)启动generator对象, generator对象运行到yield,将yield右面的表达式的值返回,并保存generator对象当前的状,因此,后面的打印都没有被执行。
5.t.send(10)
1)将输入的值10赋值给s
2)执行yield后面的表达式,即将所有print执行完毕,解析如下:
由于在第4步generator保存了对象的当前的状态,因此: i = 0, s是刚输入的值为10, i *s 当然就为0了,接着进入下一次循环,此时i= 1,执行yield表达式,结果得10,保存当前generator状态,返回10,generator停止运行。
6.t.send(11)
1)和第5步类似了,将11输入给s
2)因为第5步,generator保存了当前的对象的值,因此: i = 1, s是刚输入的值为11, i *s 当然就为11了,接着进入下一次循环,此时i= 2,执行yield表达式,结果得22,保存当前generator状态,返回22,generator停止运行。
7.接下来在调用t.send(num),和第5,6步一样,直到generator内部的循环完成,当再次调用时,将抛出异常:StopIteration
总结一下:
1. yield表达式, 四种形式:
a. 不接受输入值或者输入值是None
yield 1
b. 接受输入值
s = yield 1
c. 接受输入,但不返回数据,这样默认返回None
s = yield
d.既不接受输入,也不返回值,默认返回None
yield
第一种:当函数调用到yield时,返回yield的右边经过计算的值 ,这里说计算的意思是,yield后面可以写成函数,表达式等,
第二种:当函数调用到yield时,必须传入一个值,该值存入s中,然后返回yield后面的表达式的值并保存当前状态
第三种:只是将数据接受进来,然后执行yield后的语句,再次执行到yield时,保存当前状态并返回,这样的用例一般是
只打印一些处理消息,而不需要结果的方式。
第四种:这样的只能遍历generator内部的数据了。
2.使用generator的好处:
1)可以很方便的实现迭代器,即yield不接受输入值
2)使用generator可以减少内存的使用,因为遍历出来的值都是每次进行计算的,不用一次性全部计算完成,然后一个个
遍历,最终释放掉;另外可以在yield后面做一些操作,可以很随意的控制返回值。
3.coroutine 协程
使用yield的函数,若用send来控制,就算coroutine了,若用for循环来控制,就算generator或者iterator,使用方法大多见于
decorator, 如tornado中的gen.coroutine。
实例:
#应用:grep -rl 'root' /etc 模拟linux中的grep -rl 命令,来过滤含有root内容的文件,并打印文件名 # import os # def f1(func): #程序初始化 # def wrapper(*args, **kwargs): # g=func(*args, **kwargs) # next(g) # return g # return wrapper # #阶段一,递归的找文件的绝对路径,把路径发给阶段2 # @f1 # def search(target): # 'search file abspath' # while True: # start_path = yield # g = os.walk(start_path) # for par_dir, _, files in g: # for file in files: # file_path = r'%s\%s' % (par_dir, file) # target.send(file_path) # #阶段2,收到文件路径, 打开文件获取对象,吧文件对象发给阶段3 # @f1 # def opener(target): # 'get file obj: f = open(file_path)' # while True: # file_path = yield # with open(file_path, 'r', encoding='utf-8') as f: # target.send((file_path, f)) # #阶段三,收到文件对象,for循环读取文件的每一行内容,把每一行内容发给阶段4 # @f1 # def cat(target): # 'read file' # while True: # file_path,f = yield # for line in f: # res = target.send((file_path, line)) # if res: # break # #阶段4,收到一行内容,判断root是否在这一行,如果在,则把文件名发给阶段五 # @f1 # def grep(target, pattern): # 'grep functhion' # tag=False # while True: # file_path, line = yield tag # tag = False # if pattern in line: # target.send(file_path) # tag=True # #阶段五,收到文件名,打印结果 # @f1 # def printer(): # 'print function' # while True: # filename = yield # print(filename) # start_path1 = r'E:\Pycharmlx\June\day\day21root' # start_path2 = r'E:\Pycharmlx\June\day\day21root\t' #绝对路径 # g = search(opener(cat(grep(printer(), 'root')))) # # print(g) # g.send(start_path1) # g.send(start_path2)
yield表达式形式的更多相关文章
- python函数式编程之yield表达式形式
先来看一个例子 def foo(): print("starting...") while True: res = yield print("res:",res ...
- Python基础(9)_生成器(yield表达式形式)、面向过程编程
一.yield表达式形式 1 #装饰器,初始化含yield表达式的生成器 def init(func): def wrapper(*args,**kwargs): g=func(*args,**kwa ...
- python3 yield表达式形式应用
我们已知: 生成器函数:函数体内包含有yield关键字,该函数执行的结果是生成器 yield的功能: 1.与return类似,都可以返回值,但不一样的地方在于yield返回多次值,而return只能返 ...
- yield 表达式形式的应用
import random foods=['banana','apple','peach','grape','pear'] def deco(func): def wrapper(*args,**kw ...
- yield的表达式形式与内置函数
yield的功能: 1. 与return类似,都可以返回值,不一样在于,yield可以返回多个值而且可暂停,再次执行可继续下一步操作,return到了就停止不在继续运行. 2.为封装好的的函数能够使用 ...
- yield的表达式形式的应用(待补充)
1.yield的表达式形式应用的定义: 在一个生成器函数内,将yield赋值给一个变量,这就是yield的表达式形式.也叫生成器的表达式形式 2.send方法的定义: (1)定义: yield的表达式 ...
- yield的表达式形式、面向过程编程(grep -rl 'root' /etc)
一.yield的表达形式 def foo(): print('starting') while True: x=yield None#return 2 print('value :',x) g=foo ...
- Python开发基础-Day10生成器表达式形式、面向过程编程、内置函数部分
生成器表达式形式 直接上代码 # yield的表达式形式 def foo(): print('starting') while True: x=yield #默认返回为空,实际上为x=yield No ...
- python基础之生成器表达式形式、面向过程编程、内置函数部分
生成器表达式形式 直接上代码 1 # yield的表达式形式 2 def foo(): 3 print('starting') 4 while True: 5 x=yield #默认返回为空,实际上为 ...
随机推荐
- sklearn.svm.LinearSVC文档学习
https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html#sklearn.svm.LinearSVC 1 ...
- word2vec 评测 size_diff
This is a test for word2vecWed Nov 07 16:47:19 2018dir of model1: ./model/window3_ min_count2_worker ...
- 配置Tomcat启用Https安全协议的访问
1.首先使用keytool工具生成证书文件名为cnkey,然后拷贝此证书即文件到tomcat安装目录conf下(放到哪里都行,主要在下面配置中指明路径就好了.这里我就放这了conf) 2.配置serv ...
- SEO--网站流量提升
话术设置,提炼优质的话术 关键词的挖掘 1.头脑风暴 (开晨会,一堆人坐在一起聊.) 2.利用搜索引擎相关搜索(将关键词设置为搜索热词,利用工具:百度指数,查看关键词) 3.工具 4.长尾关键词(词比 ...
- cocos2d JS 监听键盘触摸响应事件(cc.EventListener.KEYBOARD)
除了可以监听键盘按键,还可以是终端设备的各个菜单键,都能使用同一个监听器来进行处理. //给statusLabel绑定键盘事件 cc.eventManager.addListener({ event: ...
- Response.Redirect & window.location.href
对接中信的微信H5支付时,对方(其实是微信)需要对我们的域名进行授权,即,我方需向渠道报备支付域名,微信只认可由此域名发起的支付交易. 支付中心只提供了一套支付接口供下游系统访问.因为给渠道报备的域名 ...
- Uncaught DOMException: Blocked a frame with origin "http://localhost
ajaxFileUpload上传时报错 :Uncaught DOMException: Blocked a frame with origin "http://localhost..... ...
- HDU 1251 统计难题(Trie)
统计难题 [题目链接]统计难题 [题目类型]Trie &题解: Trie的模板题,只不过这题坑点在没给数据范围,改成5e5就可以过了,用的刘汝佳蓝书模板 &代码: #include & ...
- Oracle 22表空间
数据库与表空间: 表空间实际上是数据库上的逻辑储存结构,可以把表空间理解为在数据库中开辟的一个空间,用于存放我们的数据库的对象,一个数据库可以由多个表空间构成. 表空间与数据文件: 表空间实际上是由一 ...
- URL List by Category
URLs List AI https://www.cnblogs.com/zlel/p/8882129.html Javascript Promise http://liubin.org/promis ...