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

Python028

程序开发中yield是什么,怎么用?,第1张

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 子句执行。

yield的作用主要是创建生成器 generator, 生成器也是用于迭代的,想对于普通迭代对象如list 来说,生成器不会事先生成所有的集合元素,而是边迭代边生成,占用内存更少。

如果一个函数里不是用return来返回数据,而是用yield来返回数据,那么这个函数就是生成器,注意,yield关键字只能用在函数体里面

上面generator()函数就是使用了yield的生成器,它和itertor()函数的区别就是它不会真的生成一个长度为一百万的序列,而只是记录了这一百万个数据的生成方式,所以它占用内存很少。而itertor()函数使用的使用的range(1000000)则真的会生成一百万个元素在列表里(注:python2里range是直接生成元素,python3里range则也变成了生成器)。

在迭代生成器的时候,每次遇到yield i 会返回i, 然后迭代器函数就在yield的地方暂停运行,线程切换到调用处,在调用处进入下一次for 循环时,线程又切回到生成器函数上次yield的地方继续运行。其实在线程切回到yield的时候可以传递参数给生成器

之前的生成器是通过for 循环遍历的,其实for 循环的本质就是不停的next(generator)输出下一个元素,直到遍历结束。上面的例子就是使用next函数来调用的,在generator2里yield空值,然后线程跳到了g2.send(1),send的作用就是让线程带了一个参数回到生成器里面,这个参数传给了new,然后生成器继续执行。

yield from 基本的用法是代替for 循环,yield一个可迭代对象

上面的yield from 就是简化了for循环的yield语句。

yield from 还可以接受生成器的返回值,我们知道生成器是通过yield来返回值的,return的值是无法通过for 迭代生成器来获得的,var = yield from 可以获取return

yield from 还有一个高级的用法,就是协程,后面介绍

yield(C# 参考)

在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。它的形式为下列之一:

yield return <expression>

yield break

备注 :

计算表达式并以枚举数对象值的形式返回;expression 必须可以隐式转换为迭代器的 yield 类型。

yield 语句只能出现在 iterator 块中,该块可用作方法、运算符或访问器的体。这类方法、运算符或访问器的体受以下约束的控制:

不允许不安全块。

方法、运算符或访问器的参数不能是 ref 或 out。

yield 语句不能出现在匿名方法中。

当和 expression 一起使用时,yield return 语句不能出现在 catch 块中或含有一个或多个 catch 子句的 try 块中。

yield return 提供了迭代器一个比较重要的功能,即取到一个数据后马上返回该数据,不需要全部数据装入数列完毕,这样有效提高了遍历效率。

以下是一个比较特殊的例子:

using System

using System.Collections

using System.IO

using Microsoft.Office.Interop.PowerPoint

using Microsoft.Office.Core

using System.Windows.Forms

using System.Threading

namespace test

{

public class Persons : System.Collections.IEnumerable

{

#region IEnumerable 成员

public System.Collections.IEnumerator GetEnumerator()

{

yield return "1"

Thread.Sleep(5000)

yield return "2"

Thread.Sleep(5000)

yield return "3"

Thread.Sleep(5000)

yield return "4"

Thread.Sleep(5000)

yield return "5"

Thread.Sleep(5000)

yield return "6"

}

#endregion

}

class program

{

static void Main()

{

Persons arrPersons = new Persons()

foreach (string s in arrPersons)

{

System.Console.WriteLine(s)

}

System.Console.ReadLine()

}

}

}

每隔5秒钟, 控制台就会输出一个数据,直到全部数据输入完毕。