Python 进阶:百万「并发」基础之异步编程(中篇)

HackPython 致力于有趣有价值的编程教学

简介

在上一篇,讨论了阻塞 / 非阻塞、同步 / 异步、并发 / 并行等概念,本节主要来讨论一下生成器、yield 以及 yield from 概念并进行简单的使用。

关键概念

Python 中利用了 asyncio 这个标准库作为异步编程框架,而 aysncio 以及其他多数协程库内部都大量使用了生成器,所以先从生成器聊起。

为什么会是生成器?????回想一下生成器的特性,其利用了 yield 关键字做到了随时暂停以及随时执行的能力,而协程从技术实现角度而言,它的作用其实就是一个可以随时暂停会执行的函数。

生成器

生成器与迭代器关系紧密,????其实生成器就是迭代器另一种更优雅的实现方式,其利用了 yield 关键字实现了迭代器的功能,生成器可以迭代式的利用内存空间????,让数据在需要使用时才被载入,这减少内存的消耗,其利用 yield 关键字使用了这个功能,当生成器函数执行过程中遇到 yield 就会被展厅执行,等下次迭代时再次从暂停处继续执行。

为了让生成器可以实现简单的协程,????在 Python 2.5 的时候对生成器的能力进行了增强,此时利用 yield 可以暂停生成器函数的执行返回数据,也可以通过 send () 方法向生成器发送数据,并且还可以利用 throw () 向生成器内抛出异常以实现可随时终止生成器的目的。

yield 的作用直观如下图:

从图中可看出,在一开始调用 simplecoro2 () 方法时,获得的 mycoro2 变量并不是具体的值,而是一个生成器对象,此时调用其 next () 方法进行迭代,next () 方法会让生成器函数执行到 yield 处,到 yield 后就会将紧随在其后的变量返回,接着可以利用 send () 方法将值传递到生成器中,并让暂停的函数继续从暂停处执行????,next () 与 send () 的不同之处在于 next () 并不能向生成器内部传递值而 send () 可以,可以直接使用 send (None) 来实现 next () 方法的效果。从图中也可以看出,next () 与 send () 会获得下一个 yield 返回的值。

顺带一提,for 迭代也调用了迭代器中的__next__方法,next () 内部也是使用了该方法????。

yield from

为了让生成器分成多个子生成器后可以很容易使用 next ()、send ()、throw () 等方法,Python3.3 中引入了 yield from 表达式????,它允许将一个生成器的部分操作委派给另一个生成器。

虽然 yield from 设计的目的是为了让生成器本身可以委派给子生成器,但 yield from 可以向任意可迭代对象进行委派操作????。

yield from iterable 本质其实就是 for item in iterable: yield item,只是写法更优雅了,简单使用如下

In [1]: def gen1():
   ...:     for i in 'abc':
   ...:         yield i
   ...:     for i in range(5):
   ...:         yield i
   ...:
In [2]: list(gen1())
Out[2]: ['a', 'b', 'c', 0, 1, 2, 3, 4]
In [4]: def gen2():
   ...:     yield from 'abc'
   ...:     yield from range(5)
   ...:
In [5]: list(gen2())
Out[5]: ['a', 'b', 'c', 0, 1, 2, 3, 4]

上述代码中其实涉及几个概念,其中 gen2 () 方法因为包含了 yield from 表达式,所以被称为????委派生成器,而 yield from 后接着的表达式通常称为????子生成器,上述代码中的 'abc',range (5) 都是子生成器,而调用委派生成器的代码称为????调用方。

此外,yield from 还可以直接将调用方发送的信息直接传递给子生成器,具体可以看下面代码

from collections import namedtuple
Result = namedtuple('Result', 'count average')
# the subgenerator
def averager():
    total = 0.0
    count = 0
    average = None
    while True:
        term = yield
        print('term:', term)
        if term is None:
            break
        total += term
        count += 1
        average = total / count
    return Result(count, average)
# the delegating generator
def grouper(results, key):
    while True:
        #只有当生成器averager()结束,才会返回结果给results赋值
        results[key] = yield from averager()
        print('resluts[key]:', results[key])
def report(results):
    for key, result in sorted(results.items()):
        group, unit = key.split(';')
        print('{:2} {:5} averaging {:.2f}{}'.format(result.count, group, result.average, unit))
def main(data):
    results = {}
    for key, values in data.items():
        group = grouper(results, key)
        print(type(group))
        next(group)
        for value in values:
            r = group.send(value)
            print('r:',r)
            print('value:',value)
        group.send(None)
    report(results)
data = {
    'girls;kg':[40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5],
    'girls;m':[1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43],
    'boys;kg':[39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],
    'boys;m':[1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46],
}
if __name__ == '__main__':
    main(data)

在上述代码中,grouper 函数是委托生成器????,averager 函数是子生成器????,而 main () 函数就是调度者????。

在 main () 函数中,首先通过 grouper () 获得对应的生成器对象,然后调用 next () 方法进行初步的迭代,此时会执行到 averager () 的 yield 处????,因为 yield 后没有跟对应的变量,则 yield 返回的值为 None????,该值会有 grouper () 委托生成器直接传递给 main () 调度者,观察变量 r 的打印则可,接着 for 迭代中使用委托生成器的 send () 方法,该方法发送的数据会有委托生成器直接传递给子生成器,即 averager () 函数中 term 的值,上述代码调度的关系如下图:

从图中看出,????调度者使用 send () 方法传递的数据会被委派生成器直接传递给子生成器,而子生成器 yield 的方法数据也被直接传递回调度者,如果子生成器产生 StopIteration 异常则表示子生成器已经迭代完了,此时委派生成器会接收到该异常,从而继续执行 yield from 整个表达式后的其他表达式,这里 grouper () 函数中 yield from 执行完后,就没有逻辑了。

可以看出,委派生成器具有组织多个子生成器的能力,并可以将调度者的信息转手传递给子生成器????。

结尾

在本节中,主要介绍 Python 中生成器、yield 以及 yield from 的概念与使用,在下一篇中,会接着讨论 Python 的 asyncio 框架以及 async/await 原生协程,最后欢迎学习 HackPython 的教学课程并感谢您的阅读与支持。

参考文章

Python 异步编程详解

Python 也能高并发

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
数字乡村和智慧农业的数字化转型是当前农业发展的新趋势,旨在通过应用数字技术,实现农业全流程的再造和全生命周期的管理服务。中国政府高度重视这一领域的发展,提出“数字中国”和“乡村振兴”战略,以提升国家治理能力,推动城乡融合发展。 数字乡村的建设面临乡村治理、基础设施、产业链条和公共服务等方面的问题,需要分阶段实施《数字乡村发展战略纲要》来解决。农业数字化转型的需求包括满足市民对优质农产品的需求、解决产销对接问题、形成优质优价机制、提高农业劳动力素质、打破信息孤岛、提高农业政策服务的精准度和有效性,以及解决农业融资难的问题。 数字乡村建设的关键在于构建“1+3+4+1”工程,即以新技术、新要素、新商业、新农民、新文化、新农村为核心,推进数据融合,强化农业大数据的汇集功能。数字农业大数据解决方案以农业数字底图和数据资源为基础,通过可视化监管,实现区域农业的全面数字化管理。 数字农业大数据架构基于大数据、区块链、GIS和物联网技术,构建农业大数据中心、农业物联网平台和农村综合服务指挥决策平台三大基础平台。农业大数据中心汇聚各类涉农信息资源和业务数据,支持大数据应用。信息采集系统覆盖市、县、乡、村多级,形成高效的农业大数据信息采集体系。 农业物联网平台包括环境监测系统、视频监控系统、预警预报系统和智能控制系统,通过收集和监测数据,实现对农业环境和生产过程的智能化管理。综合服务指挥决策平台利用数据分析和GIS技术,为农业决策提供支持。 数字乡村建设包括三大服务平台:治理服务平台、民生服务平台和产业服务平台。治理服务平台通过大数据和AI技术,实现乡村治理的数字化;民生服务平台利用互联网技术,提供各类民生服务;产业服务平台融合政企关系,支持农业产业发展。 数字乡村的应用场景广泛,包括农业生产过程、农产品流通、农业管理和农村社会服务。农业生产管理系统利用AIoT技术,实现农业生产的标准化和智能化。农产品智慧流通管理系统和溯源管理系统提高流通效率和产品追溯能力。智慧农业管理通过互联网+农业,提升农业管理的科学性和效率。农村社会服务则通过数字化手段,提高农村地区的公共服务水平。 总体而言,数字乡村和智慧农业的建设,不仅能够提升农业生产效率和管理水平,还能够促进农村地区的社会经济发展,实现城乡融合发展,是推动中国农业现代化的重要途径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒编程-二两

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值