百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

如何在 Python 中使用“yield”?_pythonyield详解

itomcoil 2025-02-17 12:30 21 浏览

如果你是 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 name
roster = gen_roster(names)
print(type(roster))

运行输出:

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

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)

运行输出:

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 name
roster = 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 
                break
roster = 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 
                break
roster = gen_roster(names)
for i in range(10):
    if i == 3:
        roster.close()
    print(next(roster))

运行输出:

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

总结

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

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

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

相关推荐

Python Qt GUI设计:将UI文件转换Python文件三种妙招(基础篇—2)

在开始本文之前提醒各位朋友,Python记得安装PyQt5库文件,Python语言功能很强,但是Python自带的GUI开发库Tkinter功能很弱,难以开发出专业的GUI。好在Python语言的开放...

Connect 2.0来了,还有Nuke和Maya新集成

ftrackConnect2.0现在可以下载了--重新设计的桌面应用程序,使用户能够将ftrackStudio与创意应用程序集成,发布资产等。这个新版本的发布中还有两个Nuke和Maya新集成,...

Magicgui:不会GUI编程也能轻松构建Python GUI应用

什么是MagicguiMagicgui是一个Python库,它允许开发者仅凭简单的类型注解就能快速构建图形用户界面(GUI)应用程序。这个库基于Napari项目,利用了Python的强大类型系统,使得...

Python入坑系列:桌面GUI开发之Pyside6

阅读本章之后,你可以掌握这些内容:Pyside6的SignalsandSlots、Envents的作用,如何使用?PySide6的Window、DialogsandAlerts、Widgets...

Python入坑系列-一起认识Pyside6 designer可拖拽桌面GUI

通过本文章,你可以了解一下内容:如何安装和使用Pyside6designerdesigner有哪些的特性通过designer如何转成python代码以前以为Pyside6designer需要在下载...

pyside2的基础界面(pyside2显示图片)

今天我们来学习pyside2的基础界面没有安装过pyside2的小伙伴可以看主页代码效果...

Python GUI开发:打包PySide2应用(python 打包pyc)

之前的文章我们介绍了怎么使用PySide2来开发一个简单PythonGUI应用。这次我们来将上次完成的代码打包。我们使用pyinstaller。注意,pyinstaller默认会将所有安装的pack...

使用PySide2做窗体,到底是怎么个事?看这个能不能搞懂

PySide2是Qt框架的Python绑定,允许你使用Python创建功能强大的跨平台GUI应用程序。PySide2的基本使用方法:安装PySide2pipinstallPy...

pycharm中conda解释器无法配置(pycharm安装的解释器不能用)

之前用的好好的pycharm正常配置解释器突然不能用了?可以显示有这个环境然后确认后可以conda正在配置解释器,但是进度条结束后还是不成功!!试过了pycharm重启,pycharm重装,anaco...

Conda使用指南:从基础操作到Llama-Factory大模型微调环境搭建

Conda虚拟环境在Linux下的全面使用指南:从基础操作到Llama-Factory大模型微调环境搭建在当今的AI开发与数据分析领域,conda虚拟环境已成为Linux系统下管理项目依赖的标配工具。...

Python操作系统资源管理与监控(python调用资源管理器)

在现代计算环境中,对操作系统资源的有效管理和监控是确保应用程序性能和系统稳定性的关键。Python凭借其丰富的标准库和第三方扩展,提供了强大的工具来实现这一目标。本文将探讨Python在操作系统资源管...

本地部署开源版Manus+DeepSeek创建自己的AI智能体

1、下载安装Anaconda,设置conda环境变量,并使用conda创建python3.12虚拟环境。2、从OpenManus仓库下载代码,并安装需要的依赖。3、使用Ollama加载本地DeepSe...

一文教会你,搭建AI模型训练与微调环境,包学会的!

一、硬件要求显卡配置:需要Nvidia显卡,至少配备8G显存,且专用显存与共享显存之和需大于20G。二、环境搭建步骤1.设置文件存储路径非系统盘存储:建议将非安装版的环境文件均存放在非系统盘(如E盘...

使用scikit-learn为PyTorch 模型进行超参数网格搜索

scikit-learn是Python中最好的机器学习库,而PyTorch又为我们构建模型提供了方便的操作,能否将它们的优点整合起来呢?在本文中,我们将介绍如何使用scikit-learn中的网格搜...

如何Keras自动编码器给极端罕见事件分类

全文共7940字,预计学习时长30分钟或更长本文将以一家造纸厂的生产为例,介绍如何使用自动编码器构建罕见事件分类器。现实生活中罕见事件的数据集:背景1.什么是极端罕见事件?在罕见事件问题中,数据集是...