如何在 Python 中使用“yield”?

如何在 Python 中使用“yield”?如果你是 Python 开发者,相信你一定知道 Python 中的 生成器。定义 Python 生成器的关键是使用“yield”关键字。Pyth

欢迎大家来到IT世界,在知识的湖畔探索吧!

如果你是 Python 开发者,相信你一定知道 Python 中的 生成器。定义 Python 生成器的关键是使用“yield”关键字。Python 生成器普遍用于需要大集合的场景,提高代码的可读性以及多线程等其他特定场景。

你可能知道也可能不知道如何正确使用“yield”关键字。在本文中,我将从基本用法介绍 Python 生成器。后面的部分还将介绍一些更高级的使用模式。

1. 基础

让我们在本教程中编写一个示例。假设我们公司有一群人需要一个一个待命。所以,这将是一个轮换名单。

names = ["alice","bob","chris","jack","elio"]

欢迎大家来到IT世界,在知识的湖畔探索吧!

现在,我们要从这个名称列表中定义一个 Python 生成器。代码如下。

欢迎大家来到IT世界,在知识的湖畔探索吧!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 name
roster = gen_roster(names)
print(type(roster))

运行输出:

如何在 Python 中使用“yield”?

现在,我们得到了rosterPython 生成器也是可迭代的,因此我们可以将其放入 for 循环中,一次性获取所有name

欢迎大家来到IT世界,在知识的湖畔探索吧!names = ["alice","bob","chris","jack","elio"]
def gen_roster(names):
    for name in names:
        yield name
roster = gen_roster(names)
for name in roster:
    print(name)

运行输出:

如何在 Python 中使用“yield”?

2. 使用__next__方法

好吧,在前面的示例中,在 for 循环中使用生成器并没有太大意义。使用生成器的好处是我们可以一次获得一个值。当我们处理大量集合时,这可能非常有用。也就是说,当我们创建一个生成器时,项目不会被读入内存。只有当我们试图获取下一个项目并点击yield关键字时,才会生成该项目。

因此,无论如何,重要的是获得生成器的“下一个”元素。在这种情况下,我们可以使用它的__next__()方法。

roster.__next__()
如何在 Python 中使用“yield”?

其实我们也可以按照下面的方式来做,更直观,更容易记忆。

next(roster)
如何在 Python 中使用“yield”?

你是否注意到当我们试图获取“下一个”列表元素“光标”被移动了?还记得我们在生成器的定义中定义了一个 for 循环吗?我们可以认为 for 循环将每次执行一次,直到到达关键字为止yield

这也意味着,我们的“光标”目前位于第三个名称。因此,如果我们尝试输出所有其余的项目,“alice”和“bob”将被跳过。

如何在 Python 中使用“yield”?

现在,“光标”在末尾。如果我们尝试获取下一个项目,则会抛出错误,因为没有更多列表元素。

如何在 Python 中使用“yield”?


这实际上不是我们想要的,因为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 name
roster = gen_roster(names)

for i in range(12):
    print(next(roster))
如何在 Python 中使用“yield”?

如果我们不输入数字“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))

运行输出:

如何在 Python 中使用“yield”?

在上面的代码中,我们要求程序循环 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 
                break
roster = gen_roster(names)
next_name = roster.throw(TypeError, 'Stop!')
如何在 Python 中使用“yield”?

如果没有出错,但我们仍然想终止生成器,我们可以使用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 
                break
roster = gen_roster(names)
for i in range(10):
    if i == 3:
        roster.close()
    print(next(roster))

运行输出:

如何在 Python 中使用“yield”?

上面的代码在第 4 轮关闭了生成器“roster”,所以当下一个循环试图获取下一个值时,就会抛出异常

总结

在本文中,我介绍了 Python 中最重要的“Pythonic”概念之一生成器。关键字的使用yield是 Python 生成器的关键。

不仅介绍了基本用法,还介绍了一些高级用法,例如从外部向生成器发送值、引发异常和关闭生成器。希望它可以帮助你更多地了解 Python 生成器。

如果你发现我的任何文章对你有帮助或有用,麻烦点赞或者转发。 谢谢!

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/37158.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信