在国际网站上做贸易怎么发货,工业风 网站建设,如何自己免费创建网站,wordpress前端修改影响升级在我们使用Python编译过程中#xff0c;yield 关键字用于定义生成器函数#xff0c;它的作用是将函数变成一个生成器#xff0c;可以迭代产生值。yield 的行为在不同的情况下会有不同的效果和用途。 1、问题背景
在 Python 中#xff0c;“yield” 是一种生成器#xff0…在我们使用Python编译过程中yield 关键字用于定义生成器函数它的作用是将函数变成一个生成器可以迭代产生值。yield 的行为在不同的情况下会有不同的效果和用途。 1、问题背景
在 Python 中“yield” 是一种生成器generator的实现方式。生成器是一种特殊类型的迭代器iterator它可以在运行时动态产生值。然而在某些情况下使用生成器可能会遇到令人困惑的行为。
比如下面有一个函数 x()它产生一个生成器该生成器每次调用 next() 方法时都会递减全局变量 a 的值并产生一个 yield 语句:
a 5def x():global aif a 3:raise Exception(Stop)a a - 1yield a现在让我们在 Python shell 中调用这个函数并打印出生成的值 print(x().next())
4print(x().next())
3到目前为止一切正常。但是如果我们把生成器函数的调用结果赋值给一个变量然后使用这个变量来产生值就会出现不同的行为 a 5b x()print(b.next())
4b.next()
StopIteration这次在第二次调用 b.next() 时它没有产生值而是引发了一个 StopIteration 异常。这是为什么呢
2、解决方案
要理解这种行为我们需要了解生成器的工作原理。
当我们调用一个生成器函数时它并不会立即执行函数体而是返回一个生成器对象generator object。这个生成器对象包含了函数体中的代码但它不会在调用时执行。当我们使用 next() 方法来产生值时生成器对象才会开始执行函数体。
在第一次调用 x() 时我们创建了一个新的生成器对象。这个对象在执行函数体时遇到了 a 3 这个条件并引发了一个异常。然后我们在 Python shell 中打印出了这个异常。
在第二次调用 x() 时我们又创建了一个新的生成器对象。这个对象在执行函数体时仍然遇到了 a 3 这个条件并引发了异常。
但是当我们把生成器函数的调用结果赋值给变量 b 时情况发生了变化。这使得我们可以多次调用 b.next() 来产生值。当我们第一次调用 b.next() 时生成器对象从上次中断的地方继续执行并产生了值 4。
然而当我们第二次调用 b.next() 时生成器对象已经执行到了函数体的末尾没有更多的值可以产生了。因此它引发了一个 StopIteration 异常。
为了更好地理解这种行为我们可以使用一个 for 循环来遍历生成器
def looping(stop):for i in looping(stop):yield i looping(3).next()
0looping(3).next()
0注意每次我们创建一个新的生成器循环都会从头开始。然而如果我们存储一个生成器的引用那么循环会继续从上次中断的地方继续执行 stored looping(3)stored.next()
0stored.next()
1stored.next()
2stored.next()
Traceback (most recent call last):File stdin, line 1, in module
StopIteration在循环期间每次执行 yield 语句时代码都会暂停调用 .next() 继续从上一时间中断的地方继续执行函数。
StopIteration 异常是完全正常的这是生成器传达它们已经完成的方式。一个 for 循环寻找这个异常来结束循环 for i in looping(3):
... print(i)
...0
1
2通过上述总结我们得知yield 在不同的上下文中有不同的行为但都涉及到生成器的创建或者协程的定义。所以说最终选择哪种模式还得更加自身情况来选择。