自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django

自学Python4.8 - 生成器(方式二:生成器表达式)

 

定义:生成器(generator)是一个包含yield关键字的函数,当它被调用的时候,在函数体中的代码不会被执行,而是会返回一个迭代器。
          (一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);      
              如果函数中包含yield语法,那这个函数就会变成生成器;)

  • 生成器是一个特殊的程序,可以被用作控制循环的迭代行为
  • 生成器类似于返回值为数组的一个函数,这个函数可以接收参数,可以被调用,但是,不同于一般的函数会一次性返回包含了所有数值的数组,生成器一次 只产生一个值,这样消耗的内粗数量大大减少,而且允许调用函数可以很快的开始处理前几个返回值。因此,生成器看起来像一个函数但是表现的却像一个迭代器

python提供了两种基本的生成器方式:

  • 生成器函数:也是用def来定义,利用关键字yield一次返回一个结果,阻塞,重新开始
                         每次请求一个值,就会执行生成器中的代码,知道遇到一个yield或者return语句
                         ①yield语句意味着应该生成一个值
                         ②return语句意味着要停止执行(不生成任何东西,只有在一个生成器中使用时才能进行无参数调用)
  • 生成器表达式:返回一个对象,这个对象只有在需要的时候才产生结果

2.  生成器表达式: 

 生成器表达式来自于迭代和列表解析的组合,生成器表达式和列表解析类似,但是他使用尖括号而不是方括号括起来的。

print([ x ** 3 for x in range(5)]) # 列表推导式
print((x ** 3 for x in range(5))) # 生成器表达式
print(list(x ** 3 for x in range(5)))# 两者之间转换

输出:

for n in (x ** 3 for x in range(5)):
print('%s, %s' % (n, n * n)) # 就操作而言,生成器表如果使用大量的next()函数会显得十分不方便,for循环会自动出发next函数  

输出:

[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理

[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能

举例1:

30以内所有能被3整除的数

 
举例2:
30以内所有能被3整除的数的平方

举例3:
找到嵌套列表中名字含有两个‘e’的所有名字
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
ret = [name for lst in names for name in lst if name.count('e') ==2]
print(ret)

字典推导式

举例1:

将一个字典的key和value对调

举例2:

合并大小写对应的value值,将k统一成小写

举例3:

集合推导式,自带结果去重功能

3. 生成器函数与协程生成器表达式比较

一个迭代既可以被写成生成器函数,也可以被协程生成器表达式,均支持自动和手动迭代。而且这些生成器只支持一个active迭代,也就是说生成器的迭代器就是生成器本身。

def recv():
print('Are your ready:')
while True:
n = yield #yield语句还有更给力的功能,作为一个语句出现在赋值运算符的右边,接受一个值,或同时生成一个值并接受一个值
print('总共用了 %s 秒' % n)
c = recv()
c.__next__()
c.send(100)
c.send(300)

输出:

解释:以上这种方式使用yield语句的函数称为协程。在这个例子中,对于__next__的初始调用是必不可少的,这样协程才能执行可通向第一个yield表 达式的语句。在这里协程会挂起,等待相关生成器对象send()方法给它发送一个值。传递给send()的值由协程中的yield表达式返回。 协程的运行一般是无限期的,使用方法close()可以显式的关闭它。

def split_line():
print('ready to split')
result = None
while True:
line = yield result #如果yield表达式中提供了值,协程可以使用yield语句同时接收和发出返回值
result = line.split()
s = split_line()
s.__next__()
print(s.send('1,2,3'))

输出:

解释:

这个例子中的先后顺序非常重要。首个next()方法让协程执行到yield result,这将返回result的值None。
在接下来的send()调用中,接收到的值被放到line中并拆分到result中。
send()方法 的返回值就是下一条yield语句的值。也就是说,send()方法可以将一个值传递给yield表达式,但是其返回值来自下一个yield表达式,而不是接收send()传递的值的yield表达式。

③  如果想用send()方法来开启协程的执行,必须先send一个None值,因为这时候是没有yield语句来接受值的,否则就会抛出异常

def split_line():
print('ready to split')
result = None
while True:
line = yield result #如果yield表达式中提供了值,协程可以使用yield语句同时接收和发出返回值
result = line.split()
s=split_line()
print(s.send('1 2 3'))

输出:

def split_line():
print('ready to split')
result = None
while True:
line = yield result #如果yield表达式中提供了值,协程可以使用yield语句同时接收和发出返回值
result = line.split()
s=split_line()
print(s.send(None))
print(s.send('1 2 3'))

输出:

④ 生成器的功能非常强大。协程可以用于实现某种形式的并发。在某些类型的应用程序中,可以用一个任务调度器和一些生成器或协程实现协作式用户空 间多线程,即greenlet。

yield的威力将在协程,协同式多任务处理(cooperative multitasking),以及异步IO中得到真正的体现。

...

自学Python4.8-生成器(方式二:生成器表达式)的更多相关文章

  1. 自学Python4.7-生成器(方式一:生成器函数)

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  2. 自学Python4.2 迭代器、生成器

    迭代器.生成器一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么, 因为人们很少在迭代途中往后退.另外 ...

  3. 测开之数据类型· 第3篇《列表推导式、字典推导式、2种方式创建生成器》

    坚持原创输出,点击蓝字关注我吧 作者:清菡 博客:oschina.云+社区.知乎等各大平台都有. 目录 一.列表推导式 二.字典推导式 三.2种方式创建生成器 1.生成器表达式 2.函数里面,通过 y ...

  4. Python生成器/推导式/生成器表达式

    一   生成器 生成器的本质就是迭代器 生成器的特点和迭代器一样,取值方式和迭代器一样(__next__(),  send():  给上一个yield传值) 生成器一般由生成器函数或者生成器表达式来创 ...

  5. day17 生成器, 面向过程, 三元表达式, 生成式

    1. 生成器 生成器:就是一种自定义的迭代器,是用来返回多次值自定义迭代器的好处:节省内存 return只能返回一次值,函数就立即结束了yield 1.可以挂起函数,保存函数的运行状态 2.可以用来返 ...

  6. python之序列去重以及生成器、生成器函数、生成器表达式与迭代器浅谈

    首先要明确序列值类型是否可哈希,因为可哈希的值很简单就可以用 in /not in 写个生成器去判断,如果是不可哈希的就要去转换为可哈希的再用 in/not in 去判断 原地不可变类型(可哈希): ...

  7. 自学Python4.1-文件操作

    文件操作 操作文件时,一般需要经历如下步骤: 打开文件 操作文件 关闭文件(非必须) 一.打开文件 open('文件路径', '模式')      打开文件时,需要指定文件路径和以何等方式打开文件,打 ...

  8. 自学Python4.9-生成器举例

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  9. Cookie实现商品浏览记录--方式二:JS实现

    使用Cookie实现商品浏览记录:方式二:JS方法实现cookie的获取以及写入.当某一个产品被点击时,触发JS方法.利用JS方法判断一下,此产品是否在浏览记录中.如果不存在,则将产品ID加入到coo ...

随机推荐

  1. Elasticsearch 关键字:索引,类型,字段,索引状态,mapping,文档

    1. 索引(_index)索引:说的就是数据库的名字.我这个说法是对应到咱经常使用的数据库. 结合es的插件 head 来看. 可以看到,我这个地方,就有这么几个索引,索引就是数据库,后面是这个数据库 ...

  2. MySQL之慢查询日志和通用查询

    MySQL中的日志包括:错误日志.二进制日志.通用查询日志.慢查询日志等等.这里主要介绍下比较常用的两个功能:通用查询日志和慢查询日志. 1.通用查询日志:记录建立的客户端连接和执行的语句. 2.慢查 ...

  3. js 移动端 多图上传 预览 删除 base64转为url 传给后端

    说下主要的逻辑,首先是利用input type="file",上传文件,然后判断文件类型是否是图片,这里要注意(multiple,安卓一次一张,ios可以多张). 接着把本地图片转 ...

  4. Java 验证码详解

    1 使用Servlet实现验证码,涉及的知识点主要为java 绘图技术与session保存数据. HTML页面 <html> <image src='images/logo1.jpg ...

  5. Sqlserver tablediff的简单使用

    1. 先列举一下自己简单的比较语句 tablediff -sourceserver 10.24.160.73 -sourcedatabase cwbasemi70 -sourceschema lcmi ...

  6. CIFS 与 SMB 有什么区别?

    CIFS 与 SMB 有什么区别? https://www.getnas.com/2018/11/30/cifs-vs-smb/ 网络协议 一知半解 学习一下挺好的.. 记得 win2019 已经废弃 ...

  7. ubunto启动chrome报错

    /usr/bin/google-chrome-stable[5199:5199:0703/143543.136117:ERROR:zygote_host_impl_linux.cc(88)] Runn ...

  8. 莫烦sklearn学习自修第八天【过拟合问题】

    1. 什么是过拟合问题 所谓过拟合问题指的是使用训练样本进行训练时100%正确分类或规划,当使用测试样本时则不能正确分类和规划 2. 代码实战(模拟过拟合问题) from __future__ imp ...

  9. C-Lodop对大小写敏感 不要使用大小混写

    C-Lodop是对大小写敏感的,而以前的Lodop控件,对于大小混写有可能可以用,而目前由于高版本的火狐谷歌不再支持np插件,为了兼容所有浏览器,就要使用c-lodop,或像Lodop官网的样例一样, ...

  10. webpack始出来

    一直想好好整理一下webpack,现在就整理吧. 总结自己的实际搭建的整理情况,我还是要先对自己说一句,以后给文件夹起名字的时候不要用一些特殊的关键字,比如我在做这个demo的时候,我用的文件夹名称叫 ...