通俗理解yield、yield from、async

1. yield

yield的函数则返回一个可迭代的 generator(生成器)对象,你可以使用for循环或者调用next()方法遍历生成器对象来提取结果。但是每调用一次都会暂停一下,只有你需要下个元素的时候才会生成下个元素,能节省很多内存,和一般的可迭代对象对比而言,如果你只需要这个可迭代对象的前5个数,之前生成的整个可迭代对象存储在容器中就会很浪费内存,剩余的你在这儿可能不会需要,而yield是你需要一个数据,会生成一个,不需要的时候就不用生成,不会事先把整个容器中的数全部生成,而是构建一个生成器,调用一次生成一个对象。

生成器有哪些作用?

参考: 如何理解Python中的yield用法? - 知乎 (zhihu.com)

链接:https://www.jianshu.com/p/bd8563093561

如果想具体化数据的形式,通常会将数据存储在一个列表中。但这样做,列表的内容将占用有形内存。列表越大,占用的内存资源就越多。

但是,如果数据集有某种逻辑,就不必存储在一个列表中,只需编写一个生成器,它将在需要时生成这些值,基本不占用内存。

yield 的作用就是把一个函数变成一个 generator,通常运用在带有循环的函数中,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用该函数时不会执行该函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行该函数内部的代码,执行到 yield时,该函数就返回一个迭代值。

生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
 

2.   yield from

作用1:

     yield from 的对象可以是可迭代的对象,yield from x 表达式对 x 对象所做的第一件事是,调用 iter(x),从中获取迭代器。因此,x 可以是任何可迭代的对象。

举个例子:

如果只使用  yield 构建一个生成器,那么对于嵌套的对象,需要2个循环得到一个生成器

# 字符串
astr='ABC'
# 列表
alist=[1,2,3]
# 字典
adict={"name":"wangbm","age":18}
# 生成器
agen=(i for i in range(4,8))

def gen(args):
    for item in args:
        for i in item:
            yield i

args = []
args.append(astr)
args.append(alist)
args.append(adict)
args.append(agen)
print('args:', args)
new_list=gen(args)
print('new_list:', list(new_list))

# 结果:
# args: ['ABC', [1, 2, 3], {'name': 'wangbm', 'age': 18}, <generator object <genexpr> at 0x000002ABEF096740>]
# new_list: ['A', 'B', 'C', 1, 2, 3, 'name', 'age', 4, 5, 6, 7]

对于yield from 而言,只需要一个循环就OK,如下:

# 字符串
astr='ABC'
# 列表
alist=[1,2,3]
# 字典
adict={"name":"wangbm","age":18}
# 生成器
agen=(i for i in range(4,8))

def gen(args):
    for item in args:
        yield from item

args = []
args.append(astr)
args.append(alist)
args.append(adict)
args.append(agen)
print('args:', args)
new_list=gen(args)
print('new_list:', list(new_list))

#args: ['ABC', [1, 2, 3], {'name': 'wangbm', 'age': 18}, <generator object <genexpr> at 0x000001A4577F6740>]
# new_list: ['A', 'B', 'C', 1, 2, 3, 'name', 'age', 4, 5, 6, 7]
#

作用2:

         当 yield from 后面加上一个生成器后,就实现了生成的嵌套。

def average_gen():
    total = 0
    count = 0
    average = 0
    while True:
        # 接受传入的参数值,后续参数变化后返回这个参数的值
        new_num = yield average
        # print(new_num)
        if new_num is None:
            break
        count += 1
        total += new_num
        # 更新参数值
        average = total/count

    # 每一次return,都意味着当前协程结束。
    return total ,count,average

# 委托生成器
def proxy_gen():
    while True:
        # 只有子生成器要结束(return)了,yield from左边的变量才会被赋值,后面的代码才会执行。
        total, count, average = yield from average_gen()
        print("计算完毕!!\n总共传入 {} 个数值, 总和:{},平均数:{}".format(count, total, average))

# 调用方
def main():
    calc_average = proxy_gen()
    next(calc_average)            # 预激协程
    print(calc_average.send([10,10]))  # 打印:10.0
    print(calc_average.send(20))  # 打印:15.0
    print(calc_average.send(30))  # 打印:20.0
    calc_average.send(None)      # 结束协程
    # 如果此处再调用calc_average.send(10),由于上一协程已经结束,将重开一协程

if __name__ == '__main__':
    main()

async 

参考:(5条消息) 轻松理解 Python 中的 async await 概念_Likianta 的博客-CSDN博客_async await python

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值