前言:
现时你们对“pythonyield”可能比较着重,朋友们都需要剖析一些“pythonyield”的相关内容。那么小编同时在网摘上网罗了一些有关“pythonyield””的相关内容,希望姐妹们能喜欢,各位老铁们快快来学习一下吧!如果你是 Python 开发者,相信你一定知道 Python 中的 生成器。定义 Python 生成器的关键是使用“yield”关键字。Python 生成器普遍用于需要大集合的场景,提高代码的可读性以及多线程等其他特定场景。
你可能知道也可能不知道如何正确使用“yield”关键字。在本文中,我将从基本用法介绍 Python 生成器。后面的部分还将介绍一些更高级的使用模式。
1. 基础
让我们在本教程中编写一个示例。假设我们公司有一群人需要一个一个待命。所以,这将是一个轮换名单。
names = ["alice","bob","chris","jack","elio"]
现在,我们要从这个名称列表中定义一个 Python 生成器。代码如下。
def gen_roster(names): for name in names: yield name
请注意,我们需要使用yield关键字而不是return,因此我们可以使用此函数来制作生成器。
names = ["alice","bob","chris","jack","elio"]def gen_roster(names): for name in names: yield nameroster = gen_roster(names)print(type(roster))
运行输出:
现在,我们得到了roster的Python 生成器也是可迭代的,因此我们可以将其放入 for 循环中,一次性获取所有name
names = ["alice","bob","chris","jack","elio"]def gen_roster(names): for name in names: yield nameroster = gen_roster(names)for name in roster: print(name)
运行输出:
2. 使用__next__方法
好吧,在前面的示例中,在 for 循环中使用生成器并没有太大意义。使用生成器的好处是我们可以一次获得一个值。当我们处理大量集合时,这可能非常有用。也就是说,当我们创建一个生成器时,项目不会被读入内存。只有当我们试图获取下一个项目并点击yield关键字时,才会生成该项目。
因此,无论如何,重要的是获得生成器的“下一个”元素。在这种情况下,我们可以使用它的__next__()方法。
roster.__next__()
其实我们也可以按照下面的方式来做,更直观,更容易记忆。
next(roster)
你是否注意到当我们试图获取“下一个”列表元素“光标”被移动了?还记得我们在生成器的定义中定义了一个 for 循环吗?我们可以认为 for 循环将每次执行一次,直到到达关键字为止yield。
这也意味着,我们的“光标”目前位于第三个名称。因此,如果我们尝试输出所有其余的项目,“alice”和“bob”将被跳过。
现在,“光标”在末尾。如果我们尝试获取下一个项目,则会抛出错误,因为没有更多列表元素。
这实际上不是我们想要的,因为name将用于决定谁在当前轮换中待命。换句话说,我们希望“光标”回到开头,这样所有的名字都会再次循环。
诀窍是简单的while True在 for 循环之上放置一个语句。因此,一旦所有名称都用完,for 循环将重新开始。
def gen_roster(names): while True: for name in names: yield name
现在,假设我们想要一个有 12 个名字的名单。我们只有 5 名员工。因此,它们将被旋转。
names = ["alice","bob","chris","jack","elio"]def gen_roster(names): while True: for name in names: yield nameroster = gen_roster(names)for i in range(12): print(next(roster))
如果我们不输入数字“12”,则生成器可以无限期地生成更多name。
向生成器发生一个值
生成器的一种高级用法是向生成器发送一个值。该值将成为当前yield 表达式的结果,该方法返回生成器生成的下一个值。
所以,不要指望生成器会返回我们刚刚发送的值,因为它会返回下一个。但是,我们可以使用它在生成器内部做一些事情。例如,我们可以通过向无限生成器发送某个值来停止它。
def gen_roster(names): while names: for name in names: current_name = yield name if current_name == 'stop': names = None break
如果从外部发送值“stop”,则生成器已定义为终止循环。因此,我们可以验证如下行为。
names = ["alice","bob","chris","jack","elio"]def gen_roster(names): while names: for name in names: current_name = yield name if current_name == 'stop': names = None break roster = gen_roster(names)for i in range(10): if i == 3: roster.send('stop') print(next(roster))
运行输出:
在上面的代码中,我们要求程序循环 10 次。然而,对于第 4 轮,我们将值“stop”传递给生成器。结果,只输出了 3 个名字,并且生成器在第 4 轮就停止了,而不是循环了 10 次。
当我们想要在多线程编程场景中更改生成器的行为或规则时,send 方法将非常有用。
停止生成器—抛出异常并关闭
当出现异常问题时,我们可以使用该throw()方法在生成器暂停时引发异常。我们可以自定义错误类型。出于本文章中的演示目的,为了方便起见,我将简单地使用“TypeError”。
names = ["alice","bob","chris","jack","elio"]def gen_roster(names): while names: for name in names: current_name = yield name if current_name == 'stop': names = None breakroster = gen_roster(names)next_name = roster.throw(TypeError, 'Stop!')
如果没有出错,但我们仍然想终止生成器,我们可以使用close()生成器的方法。当我们有一个无限生成器并且我们想在某个点停止它时,这将非常有用
names = ["alice","bob","chris","jack","elio"]def gen_roster(names): while names: for name in names: current_name = yield name if current_name == 'stop': names = None breakroster = gen_roster(names)for i in range(10): if i == 3: roster.close() print(next(roster))
运行输出:
上面的代码在第 4 轮关闭了生成器“roster”,所以当下一个循环试图获取下一个值时,就会抛出异常
总结
在本文中,我介绍了 Python 中最重要的“Pythonic”概念之一生成器。关键字的使用yield是 Python 生成器的关键。
不仅介绍了基本用法,还介绍了一些高级用法,例如从外部向生成器发送值、引发异常和关闭生成器。希望它可以帮助你更多地了解 Python 生成器。
如果你发现我的任何文章对你有帮助或有用,麻烦点赞或者转发。 谢谢!
标签: #pythonyield #pythonyield函数 #python中yield函数怎么用 #python yieid #python中yield函数的用法