Python语法之yield用法浅析

python 中 yield 的使用方法一直让我头疼,头疼的原因无非以下几点:

  1. 不明白 yield是什么
  2. 理不清它到底要怎么使用
  3. 不清楚在什么情况下使用yield

接下来,我主要从以上几点依次来说明

  1. yield是什么?

    yield 是Python 中的一个关键字,yield 表面上有产生、生成的意思。

    如果你对yield一点概念都没有的话,你可以把yield “当成” return 理解,

    我们都知道,return 函数的结束时调用的,那么yield也是一样,当函数体内执行到yield这条语句后,程序将会发生中断,不在执行yield下面的语句。

    执行func函数后,控制台并没有打印输出 hello world ,这也是和return的区别。程序中断了,我们该怎么去执行它呢? 你要记得,函数中出现yield,那么这个函数就变成了一个迭代器,如何执行迭代器呢?使用next()方法可以执行

def func():
    print('hello world!')
    x = yield 1
    print(x)
y = func()
print(next(y))
输出:
# hello world
# 1 
# 

执行结果分析:
· 程序开始执行以后,因为func函数中有yield关键字,所以func函数并不会真的执行,而是先得到一个生成器y(相当于一个对象)
· 直接调用 next(y),func函数才正式开始执行,先执行print(“hello world”)语句,然后执行 yield 1,这里和 return 关键字表达的意思一样,返回一个值 1,此时并没有执行 x 的赋值!
当我再次调用 next(y)的时候,会发现控制台会打印输出None,并不是我们想象的那样,x 的值为1

我们第一次调用 next(y)表示的是启动这个生成器,执行到 yield语句时发生了程序中断。下一次调用next(y)时,从上一次中断的地方继续执行下去

  1. yield怎么使用?

    上述说明后,我们可以大致了解到yield是什么。接下来,将说说yield两个方面的使用。

    · 生成器

def gen(x):
    while x > 0:
        yield x
        x = x - 1
for i in gen(10):
    print(i)

当然也可以使用 next() 来产出值:

c = gen(3)
print(type(c))  # <class 'generator'>
g = gen(2)
print(next(g)) # 2
print(next(g)) # 1
print(next(g)) # 由于生成器中没有值了,再次取 报错

我这里描述生成器不太具体,可以参考这个网站。

完全理解生成器


· 从生成器 ---->>>>> 协程

我们通常比较常用的是多线程或者多进程,但是协程我们一般比较少用。
*大概是因为大多初学者用不明白吧哈哈哈 *
“协程就不仅仅是产出值了,而是能消费发送给它的值。”
以上这句是协程的关键句,看到这句话,是不是跟我一样不觉明厉呢~
我们接下去看

在第一个代码里,就算我们执行了两次 next(y),发现 x 的值为None,也就是yield 1 并不是对 x 进行赋值的,那么我们该如何对x 进行赋值呢?

这里我们需要使用 .send()方法,让我们瞧一瞧代码

def search_string(s):
    print("寻找字符串 {}".format(s))
    while True:
        x = yield
        if s in x:
            print('{} : 成功找到~ '.format(x))

# 还是一个生成器
g = search_string('python')
print(g) # <generator object search_string at 0x0000011048B931B0>
# 激活协程!只能用一次,也可以用g.send(None)来代替next(g)
next(g)  # 寻找字符串 python
# 使用.send(...)发送数据,发送的数据会成为生成器函数中yield表达式值,即变量x的值
g.send('python is beautiful')
# python is beautiful : 成功找到~ 
# 关闭
g.close()

代码说完啦,需要注意以下几点:
· 生成器用于生成供迭代的数据
· 协程是数据的消费者
· 协程与迭代无关
· 虽然在协程值会使用yield产出值,但这与迭代无关

  1. 什么情况下使用yield 呢?
    以上说了那么多,我们都可以用简单的一个列表解决了呀。为什么还要这么费劲地使用yield呢?
    “存在即是合理滴”
    当我们的数据量很大的时候,更有经验的开发者会指出,函数在运行中占用的内存会随着列表的长度的增大而增大,如果要控制内存占用,最好不要用 List来保存中间结果,而是通过 iterable 对象来迭代。这样,我们的yield就派上用场啦~

    总结:yield 使用对初学者确实不太友好,但是我们多调用几次、多查查资料,相信大家都可以学会yield的使用方法!

猜你喜欢

转载自blog.csdn.net/weixin_42218582/article/details/90743448