程序开发中yield是啥,怎么用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序开发中yield是啥,怎么用?相关的知识,希望对你有一定的参考价值。

参考技术A yield 表达式在定义 generator 函数或是 asynchronous generator 的时候才会用到。 因此只能在函数定义的内部使用yield表达式。 在一个函数体内使用 yield 表达式会使这个函数变成一个生成器,并且在一个 async def 定义的函数体内使用 yield 表达式会让协程函数变成异步的生成器。
由于它们会对外层作用域造成附带影响,yield 表达式不被允许作为用于实现推导式和生成器表达式的隐式定义作用域的一部分。
在 3.8 版更改: 禁止在实现推导式和生成器表达式的隐式嵌套作用域中使用 yield 表达式。
下面是对生成器函数的描述,异步生成器函数会在 异步生成器函数 一节中单独介绍。
当一个生成器函数被调用的时候,它返回一个迭代器,称为生成器。然后这个生成器来控制生成器函数的执行。当这个生成器的某一个方法被调用的时候,生成器函数开始执行。这时会一直执行到第一个 yield 表达式,在此执行再次被挂起,给生成器的调用者返回 expression_list 的值。挂起后,我们说所有局部状态都被保留下来,包括局部变量的当前绑定,指令指针,内部求值栈和任何异常处理的状态。通过调用生成器的某一个方法,生成器函数继续执行。此时函数的运行就和 yield 表达式只是一个外部函数调用的情况完全一致。恢复后 yield 表达式的值取决于调用的哪个方法来恢复执行。 如果用的是 __next__() (通常通过语言内置的 for 或是 next() 来调用) 那么结果就是 None. 否则,如果用 send(), 那么结果就是传递给send方法的值。
所有这些使生成器函数与协程非常相似;它们 yield 多次,它们具有多个入口点,并且它们的执行可以被挂起。唯一的区别是生成器函数不能控制在它在 yield 后交给哪里继续执行;控制权总是转移到生成器的调用者。
在 try 结构中的任何位置都允许yield表达式。如果生成器在(因为引用计数到零或是因为被垃圾回收)销毁之前没有恢复执行,将调用生成器-迭代器的 close() 方法. close 方法允许任何挂起的 finally 子句执行。

python中return和yield怎么用的?两个有啥区别?

yield
yield是用于生成器。什么是生成器,你可以通俗的认为,在一个函数中,使用了yield来代替return的位置的函数,就是生成器。它不同于函数的使用方法是:函数使用return来进行返回值,每调用一次,返回一个新加工好的数据返回给你;yield不同,它会在调用生成器的时候,把数据生成object,然后当你需要用的时候,要用next()方法来取,同时不可逆。你可以通俗的叫它"轮转容器",可用现实的一种实物来理解:水车,先yield来装入数据、产出generator object、使用next()来释放;好比水车转动后,车轮上的水槽装入水,随着轮子转动,被转到下面的水槽就能将水送入水道中流入田里。
def func3():
for i in range(1,5):
yield i#装入
gob = func3()#generator 类型
print next(gob)#1 释放的第一个装入的数据,(先入先出)
print next(gob)#2
print next(gob)#3
print next(gob)#4
print next(gob)#报错
复制代码
return
这个大家都知道了,一句话,return既可以终止函数的执行,也可以返回函数加工处理好的数据,只是这个数据需要一个载体来进行保存,通常是变量。非条件判断的时候,只要遇见return,函数就结束执行。
参考技术A 常看到别人使用或讨论yield语法,能搜到的中文解释却不多,今天决心搞定yield,把暂时的理解贴到这里.

搞定yield之前: 叠代器(iterator)

发现yield: 生成器(constructor)

使用yield: 递归调用

1. iterator

叠代器最简单例子应该是数组下标了,且看下面的c++代码:

int array[10];

for ( int i = 0; i < 10; i++ )

printf("%d ", array[i]);

叠代器工作在一个容器里(array[10]),它按一定顺序(i++)从容器里取出值(array[i])并进行操作(printf("%d ", array[i])。

上面的代码翻译成python:

array = [i for i in range(10)]

for i in array:

print i,

for i in array干了什么(别乱想)?首先,array作为一个list是个容器,其次list这个内建类型有默认的next行为,python发现这些之后采 取的秘密的没被各位看到的动作是:拿出array这丫容器的叠代器,从里面next一下把值给i供for循环主体处置,for把这个值print了。

现在的问题是数据可以做容器叠代,代码可以吗?

怎么不行,碗碟可以用来放菜,wk们不就联想出用nt盛吗,当然我们的yield不会那么yellow + bt

2. constructor

怎么把函数变成constructor? 在函数体里有yield就行了!

def gen():
print 'enter'
yield 1
print 'next'
yield 2
print 'next again'

for i in gen():
print i

各位!python看到gen函数里出现yield,知道可以用next了,问题是怎么对代码这个容器玩next?

从容器里拿到iterator的时候它还什么也不是,处在容器入口处,对于数组来说就是下标为-1的地方,对于函数来说就是函数入口嘛事没干,但是万事俱备就欠next。

开始for i in g,next让itreator爬行到yield语句存在的地方并返回值,

再次next就再爬到下一个yield语句存在的地方并返回值,依次这样直到函数返回(容器尽头)。
您一定看出来上面代码的输出是:

enter
1
next
2
next again

如果没看出来请不要往下看了免得反被yield搞定。

3. 使用yield

yield的代码叠代能力不但能打断函数执行还能记下断点处的数据,下次next书接上回,这正是递归函数需要的。

例如中序遍历二叉树:

(应该是David Mertz写的)

def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x

for n in inorder(tree)

print n

当然yield这种代码next的能力还可以用在其它方面,发现拍案的在贴咯。

参考资料:http://www.sqlite.com.cn/MySqlite/11/413.Html

本回答被提问者采纳

以上是关于程序开发中yield是啥,怎么用?的主要内容,如果未能解决你的问题,请参考以下文章

python中yield是啥意思

计算机中异步生成器函数的用法是啥?

ejs中的布局`yield`方法是啥?

微信小程序是啥,怎么用?

patch是啥,怎么用?

RC文件如何打开?RC文件怎么打开?RC文件是啥