locust之协程(2)

16 篇文章 11 订阅 ¥19.90 ¥99.00

目录

生成器介绍

yield使用

yield from的用法


 

  • 生成器介绍

生成器是拿来干嘛的?没有生成器之间,我们有一个东西叫列表解析式,说白了,就类似如下:

a=[i for i in range(999999)]

它有啥优点?适合新人入门,运行速度快,易于编写。但缺点呢?我们可以理解为一下子生成了整个列表并加载到内存中。

也就是吃内存,后面的同步代码要等你加载完才能运行。

那再说生成器,一个是带个yield就搞定,一个是圆括号形式,就是如上的中括号换成圆括号,如下:

a=(i for i in range(999999))

本质就是,它自带了一个"return"。这个return每次只返回一个对象。它不会一次性构建整个列表,而是通过迭代的方式去惰性的加载。打个比方就是。所有的包子都做好了,但是有人下单,我才会去烤箱加热,然后卖出去。而不是全部先放蒸笼保温,那样我的蒸笼(内存)就那么大,我就不能腾出空间(cpu,内存)去做其他事情了。所以它做了2件事情:保存运行的状态,返回值.

我们来看看a是什么:

 返回的是一个迭代器,也就是它不会返回给你一个具体的结果,并且它本质就是一个迭代器。你需要调用for循环来迭代输出,而for循环就自动帮你调用了next函数来迭代输出。而yield也是如此。不外乎隐式或者显式的调用next。

  • yield使用

yield相关我们常用的有next,send,__next__,close等

next和__next__的作用就是按需取下一个值。close就是销毁了这个生成器。send的作用是给yield的左边传参。当然第一次调用的时候,因为yield的执行顺序是先右边再左边,所以,我们遇到yield就停止了运行,此时send是无法给左边赋值的,那我们第一次调用只能send(None)。send其他就给next保持一致了。我们这里举个小小的例子吧

def gen_test():
    value = 0
    while True:
        s = yield value
        print('s=', s)
        value += 1


m = gen_test()
m.send(None)
for i in range(10):
    m.send(i)
    

 

下面我们运行看看效果:

这里我们每次有个参数s,它是用来接收send传值的。

至于为什么第一次使用None进行传值,是因为第一次我们遇到yield就会暂停。而并没有进行赋值操作。所以我们传None。

当然,这只是我们的猜测,具体是不是赋值是在第二次完成,我们可以进行一个小小的实验看看效果。

 

def gen_test():
    value = 0
    while True:
        s = yield value
        print('s=', s)
        value += 1



m = gen_test()
m.send(None)
print('进行第二次send!')
m.send(1)

OK,看输出结果。确实是在第二次send的时候我们才能接收到send的值,而第一次必须传None,我们从他的祖先去看看。

OK,看了下它的底层,确实是必须在一个生成器第一次迭代的时候必须传None。

  • yield from的用法

下面介绍下yield from。要用yield from,一样的,需要实现__iter__和__next__ 方法,至于为什么他们对照的是for循环和next。则是对接的相应的协议,这里我们就无须深究了。

我们先看看它是否包含了这2个方法。依然是通过代码来举例:

def gen_test(args):
    yield from args

if __name__ == '__main__':
    s = gen_test('abc')
    print(list(s))
    iter_index = dir(s).index('__iter__')
    next_index = dir(s).index('__next__')
    print(dir(s)[iter_index])
    print(dir(s)[next_index])

看看结果;

没问题,它依然是个生成器 。这里我们看成2个单词来理解,yield,from。第一个动作是生成,第二个动作是从的意思。

合在一起,我们可以理解为从哪里产生结果。

yield是直接生成,而yield from则是从子生成器里生成。因为它具有迭代的性质,如果我们还是可以通过迭代的方式来输出。

这里的从哪里生成我们就可以理解为:

def gen_from(*args):
    for items in args:
        for item in items:
            yield item

这里我们只是简化成了如下

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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值