1.生成器 #本质就是迭代器

1.1 生成器的构建方式

在python中有三种方式来创建生成器:

​ 1.通过生成器函数

​ 2.通过生成器推导式

​ 3.python内置函数或者模块提供

1.2 生成器函数

我们先来研究通过生成器函数构建生成器。

def func():
    print(11)
    return 22

ret = func()
print(ret)
# 运行结果:
11
22

将函数中的return换成yield,这样func就不是函数了,而是一个生成器函数

def func():
    print(11)
    yield 22

我们这样写没有任何的变化,这是为什么呢? 我们来看看函数名加括号获取到的是什么?

def func():
    print(11)
    yield 22

ret = func()
print(ret)

# 运行结果:
<generator object func at 0x000001A575163888>

当我们调用函数的时候函数体里的代码会进行执行,当执行到yield的关键字的时候,发现我们是想声明一个生成器.程序就会返回一个生成器给我们

生成器的本质就是迭代器.迭代器如何取值,生成器就如何取值。所以我们可以直接执行next()或**_ _ next _ _()**方法来执行以下生成器

def func():
     print("111")
     yield 222

gener = func() # 这个时候函数不会执⾏. 而是获取到生成器
ret = next(gener) # 这个时候函数才会执行  推荐使用next()
#ret = gener.__next__() # 这个时候函数才会执行
print(ret)  # 并且yield会将func生产出来的数据 222 给了 ret。  

结果:
111
222

并且我的生成器函数中可以写多个yield。

def func():
    print(11)
    yield 22
    print(33)
    yield 44

print(func().__next__())    #启动了一个生成器
print(func().__next__())    #启动了另一个生成器

# 运行结果:
11
22
11
22
def func():
    print("111")
    yield 222
    print("333")
    yield 444

gener = func()
ret = gener.__next__()
print(ret)
ret2 = gener.__next__()
print(ret2)
ret3 = gener.__next__()
# 最后⼀个yield执⾏完毕. 再次__next__()程序报错   StopIteration异常
print(ret3)

当程序运行完最后一个yield,那么后面继续运行next()程序会报错,一个yield对应一个next,next超过yield数量,就会报错,与迭代器一样。

yield与return的区别:

return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。

yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。

应用场景:

我们来看一下这个需求:老男孩向楼下卖包子的老板订购了10000个包子.包子铺老板非常实在,一下就全部都做出来了 

def eat():
    lst = []
    for i in range(1,10000):
        lst.append('包子'+str(i))
    return lst

e = eat()
print(e)

这样做没有问题,但是我们由于学生没有那么多,只吃了2000个左右,剩下的8000个,就只能占着一定的空间,放在一边了。如果包子铺老板效率够高,我吃一个包子,你做一个包子,那么这就不会占用太多空间存储了,完美。

def eat():
    for i in range(1,10000):
        yield '包子'+str(i)

e = eat()
for i in range(200):
    next(e)

这两者的区别:

第一种是直接把包子全部做出来,占用内存。

第二种是吃一个生产一个,非常的节省内存,而且还可以保留上次的位置。

def eat():
    for i in range(1,10000):
        yield '包子'+str(i)

e = eat()
for i in range(200):
    next(e)
for i in range(300):
    next(e)
# 多次next包子的号码是按照顺序记录的。

1.3 send 方法(了解)

接下来我们再来认识一个新的东西,send方法

# next只能获取yield生成的值,但是不能传递值。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')

g = gen('alex')
next(g)
next(g)
next(g)

# 而使用send这个方法是可以的。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield 222
        print(f'{name} start to eat {food}')

g = gen('alex')
next(g)  # 第一次必须用next让指针停留在第一个yield后面
# 与next一样,可以获取到yield的值
ret = g.send('骨头')
print(ret)

结果:
alex ready to eat
alex start to eat 骨头
222

def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')

g = gen('alex')
next(g)
# 还可以给上一个yield发送值
g.send('骨头')
g.send('狗粮')
g.send('香肠')

send和next()区别:

相同点:

send 和 next()都可以让生成器对应的yield向下执行一次。

都可以获取到yield生成的值。

不同点:

第一次获取yield值只能用next不能用send( 可以用send(None) )。

send可以给上一个yield置传递值。

1.4 yield from

在python3中提供一种可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回

# 对比yield 与 yield from
def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield lst
g = func()
print(g)
print(next(g))  # 只是返回一个列表

结果:
<generator object func at 0x0000018C18AB94F8>
['卫龙', '老冰棍', '北冰洋', '牛羊配']

def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield from lst
g = func()
print(g)
# 他会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。
print(next(g))
print(next(g))
print(next(g))
print(next(g))

结果:
<generator object func at 0x00000213E7D194F8>
卫龙
老冰棍
北冰洋
牛羊配

'''
yield from ['卫龙','老冰棍','北冰洋','牛羊配']
等同于:
    yield '卫龙'
    yield '老冰棍'
    yield '北冰洋'
    yield '牛羊配'

1.5 yield from 小坑

def func():
    lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配']
    lst2 = ['馒头', '花卷', '豆包', '大饼']
    yield from lst1
    yield from lst2

g = func()
for i in g:
    print(i)

结果:
卫龙
老冰棍
北冰洋
牛羊配
馒头
花卷
豆包
大饼
返回的结果是将第一个列表的元素全部返回后,在返回第二个列表

百万年薪python之路 -- 生成器的更多相关文章

  1. 百万年薪python之路 -- 并发编程之 协程

    协程 一. 协程的引入 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两 ...

  2. 百万年薪python之路 -- 面向对象之 反射,双下方法

    面向对象之 反射,双下方法 1. 反射 计算机科学领域主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省) python面向对象中的反射:通过字符串的形式操作对象相关的属性.python ...

  3. 百万年薪python之路 -- 面向对象之继承

    面向对象之继承 1.什么是面向对象的继承 继承(英语:inheritance)是面向对象软件技术当中的一个概念. 通俗易懂的理解是:子承父业,合法继承家产 专业的理解是:子类可以完全使用父类的方法和属 ...

  4. 百万年薪python之路 -- 数据库初始

    一. 数据库初始 1. 为什么要有数据库? ​ 先来一个场景: ​ 假设现在你已经是某大型互联网公司的高级程序员,让你写一个火车票购票系统,来hold住十一期间全国的购票需求,你怎么写? 由于在同一时 ...

  5. 百万年薪python之路 -- 内置函数练习

    1.整理今天笔记,课上代码最少敲3遍. 2.用列表推导式做下列小题 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母 lst = [["a","b"],[ ...

  6. 百万年薪python之路 -- 推导式

    2.1列表推导式 首先我们先看一下这样的代码,给出一个列表,通过循环,想列表中添加1~10: li = [] for i in range(1,11): li.append(i) print(li) ...

  7. 百万年薪python之路 -- JS基础介绍及数据类型

    JS代码的引入 方式1: <script> alert('兽人永不为奴!') </script> 方式2:外部文件引入 src属性值为js文件路径 <script src ...

  8. 百万年薪python之路 -- 前端CSS样式

    CSS样式 控制高度和宽度 width宽度 height高度 块级标签能设置高度和宽度,而内联标签不能设置高度和宽度,内联标签的高度宽度由标签内部的内容来决定. 示例: <!DOCTYPE ht ...

  9. 百万年薪python之路 -- MySQL数据库之 Navicat工具和pymysql模块

    一. IDE工具介绍(Navicat) 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具,我们使用Navicat工具,这个工具本质上就是一个socket客户端,可视化的连接 ...

随机推荐

  1. 【深入学习MySQL】MySQL的索引为什么使用B+树?

    前言 在MySQL中,无论是Innodb还是MyIsam,都使用了B+树作索引结构(这里不考虑hash等其他索引).本文将从最普通的二叉查找树开始,逐步说明各种树解决的问题以及面临的新问题,从而说明M ...

  2. [Leetcode] 第324题 摆动排序II

    一.题目描述 给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序. 示例 1: 输入: nums ...

  3. 【linux】【ELK】搭建Elasticsearch+Logstash+Kibana+Filebeat日志收集系统

    前言 ELK是Elasticsearch.Logstash.Kibana的简称,这三者是核心套件,但并非全部. Elasticsearch是实时全文搜索和分析引擎,提供搜集.分析.存储数据三大功能:是 ...

  4. 基于WeChat的消息存储备份、远程控制、小功能项目开源分享计划

    WeChat+ 关于该项目 起源 该项目的起因是一个比较程(老)序(油)猿(条)的理由,有一天我发现我下班时间比较早,有点尴尬,但是又不想没事干还坐在公司,那么如何解决我的问题呢,初步想法是远程控制电 ...

  5. 制作你的第一个dockerfile文件

    From this lesson you will从这里你将学到1,Make a Dockerfile制作一个Dockerfile2,Build a Docker Image and run构建镜像并 ...

  6. 夯实Java基础系列17:一文搞懂Java多线程使用方式、实现原理以及常见面试题

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  7. Scala 学习笔记之集合(4)

    集合的模式匹配操作: object CollectionDemo5 { def main(args: Array[String]): Unit = { //集合模式匹配1 val ls = List( ...

  8. 【CV现状-3.3】特征提取与描述

    #磨染的初心--计算机视觉的现状 [这一系列文章是关于计算机视觉的反思,希望能引起一些人的共鸣.可以随意传播,随意喷.所涉及的内容过多,将按如下内容划分章节.已经完成的会逐渐加上链接.] 缘起 三维感 ...

  9. 在我的新书里,尝试着用股票案例讲述Python爬虫大数据可视化等知识

    我的新书,<基于股票大数据分析的Python入门实战>,预计将于2019年底在清华出版社出版. 如果大家对大数据分析有兴趣,又想学习Python,这本书是一本不错的选择.从知识体系上来看, ...

  10. redis之spring应用

    前言 读本文之前,需要大家对redis有所了解,大家可以去看一下我之前分享的redis安装及简单使用这一随笔,而本文我将跟大家分享学习一下redis与spring的集成.当然,首先需要打开我们的red ...