Transcription
欢迎来到本课程:Python 构建智能体必备知识。本课程将帮助您掌握自主智能背后的技术栈。本课程旨在带您从 Python 核心语法,到数据处理和 API 集成的复杂性,最终实现部署复杂的语言模型。您将学会编写代码和构建能够进行推理、使用工具并利用专有和开源人工智能解决现实世界问题的系统。我是 Prashant Sahu,很高兴在这里与您一起踏入编码、数据和人工智能的世界。在本课程中,我们将采取实践方法进行学习。我们将从模块一的基础知识开始,深入探讨 Python 基础、变量、数据类型、函数等。在本模块结束时,您将能够编写清晰、高效的 Python 代码,并为应对复杂任务打下坚实的基础。接下来,在模块二中,我们将处理文件和数据库。我们将探索 pandas,它是 Python 中最流行的数据分析库之一,并实践数据库和 SQL。您将学会如何将 Python 连接到数据库并有效地管理数据,这是任何有抱负的人工智能从业者的关键技能。在模块三中,我们将探讨 API,了解它们是什么,为什么它们至关重要,以及如何在 Python 中使用它们。您将学会连接外部服务,处理 JSON 数据,并应对身份验证和速率限制等常见挑战。我们将向您介绍 API 如何为人工智能代理和大型语言模型提供支持,这将使事情变得更加令人兴奋。最后,在模块 4 中,我们将深入研究语言模型,通常称为 LLM。您将学会如何使用 OpenAI 等库,并探索 hugging face 等开源工具。我们将介绍如何访问提示并与 LLM 进行交互,让您一窥构建智能系统的奥秘。总而言之,在本课程结束时,您不仅将理解 Python 编程,还将获得处理数据、连接 API 和与尖端语言模型交互的实践经验。我将全程指导您,我迫不及待地想看到您将创造出什么。此外,如果您想深入了解生成式人工智能、机器学习和深度学习,请随时查看我团队制作的一些免费课程。在深入探讨 Python 及其在数据科学中的相关性之前,我想快速概述一下 Python 是什么,以及为什么它对当今的数据专业人士如此重要。您可能知道,Python 是由 Guido van Rossum 于 1991 年创建的。自那时以来,它一直由 Python 软件基金会开发和维护,并已发展成为全球使用最广泛的编程语言之一。现在,让我们谈谈 Python 的背景。Python 被称为一种高级通用编程语言。Python 因其可读性和灵活性而变得极其受欢迎。它被广泛应用于科学计算、Web 开发和人工智能等各个领域。它最大的优势之一是它是一种解释型语言,这意味着它在虚拟环境中运行,这使其具有平台独立性。这意味着它几乎可以在任何系统上运行,如 Windows、Mac OS 或 Linux,而不会遇到太多麻烦。那么,为什么我们要为数据科学使用 Python 呢?简而言之,它满足了所有要求。首先,Python 拥有一个庞大而活跃的社区。这非常有帮助,因为您可以获得无数的教程、论坛,甚至可以解决您可能遇到的问题,从而使学习曲线更加平缓。其次,Python 的语法非常易于理解,这使得数据科学家能够专注于解决复杂问题,而不是花费太多时间在编码的细节上。它也是开源的,这意味着它可以免费使用,并且全球的开发人员都在不断改进它。另一个巨大的优势是 Python 丰富多样的库,如 pandas、numpy、matplotlib 和 scikit-learn。这些库使数据操作、可视化和机器学习等任务更加轻松高效。Python 在数据科学中的广泛应用也转化为大量的就业机会,这是另一个巨大的优势。在开始编码之前,正确设置您的系统非常重要。对于数据科学,许多开发人员更喜欢在集成环境(如 Jupyter Lab 或 Jupyter Notebook)中工作。Jupyter Lab 允许您在一个地方编写、执行和记录 Python 代码,非常适合数据分析和可视化。我们将逐步介绍安装和设置 Jupyter Lab 的步骤,这将确保您在本课程中拥有正确的 Python 工作环境。现在,让我们去 Google 搜索 Anaconda。我们将点击第一个链接,这是您可以开始下载 Python Anaconda 发行版的网页。在此页面上,您可以找到下载 Anaconda 发行版的链接。所以,如果您看到提交按钮下方有一个跳过注册的链接。让我们跳过注册,直接进入下载页面。这是下载页面。根据您的操作系统,您可以点击链接下载安装程序文件。我这里使用的是 Windows 系统。我将点击 64 位安装程序,它的大小为 912 兆字节。下载可能需要一些时间。所以,让我们等待。一旦我们下载了 Anaconda 安装文件,双击以开始安装。好的。我双击了安装文件,这将出现安装向导。所以,让我们点击下一步。同意许可协议,然后它会显示一个屏幕,询问是仅为自己安装还是为所有用户安装。选择“仅我”选项,这是推荐的选项,然后它将根据操作系统选择默认安装路径。确保您的 C 盘有足够的空间。默认安装目录是 C:\Users\用户名\Anaconda3,并且有一些选项供您选择是否要在系统路径中添加 Anaconda 或 Python。选择默认选项,然后点击安装。这需要一些时间来安装,大约 2 到 3 分钟。这取决于您的系统配置。所以,让我们等待。安装完成后,我们将回来。安装完成后,将出现此窗口。只需点击下一步,然后下一步,最后点击完成。它将为您提供启动 Anaconda Navigator 的选项,我们将保留选中状态,并取消选中最后一个选项。好的,Anaconda Navigator 已启动。窗口看起来是这样的。我将点击“不再显示此内容”。所以,让我们看看 Anaconda Navigator 中安装了哪些软件包。任何显示“启动”的软件都是在安装 Anaconda Navigator 时安装的,这意味着 PyCharm 未安装。如果您看到 Anaconda 工具箱已安装,Notebooks 已安装,Jupyter Lab 已安装。好的,Jupyter Notebook 已安装,在本课程中我们将广泛使用 Jupyter Lab 和 Jupyter Notebook。所以,让我们再次点击 Jupyter Lab 启动。这需要几分钟才能启动。请记住,Jupyter Lab 将在浏览器窗口中启动。我已经在浏览器窗口中启动并运行了 Jupyter Lab。有一个小警告。只要您在此处运行 Jupyter Lab,请不要关闭 Anaconda Navigator 窗口。默认安装目录显示在左侧。这是您可以看到的文件浏览器窗口,您可以从这里启动 Jupyter Notebook。您可以访问 Python 控制台或终端。您还可以从这里创建 requirement.txt 文件,还可以创建扩展名为 .md 的 Markdown 文件。您可以创建扩展名为 .py 的标准 Python 文件,还可以访问 Anaconda 中的其他应用程序。好的。所以,首先我们将学习如何在 Jupyter Lab 中创建一个文件夹,然后我们将学习如何从 Anaconda 环境创建一个新的 Jupyter Notebook,并查看。好的,所以首先您需要决定要将代码文件保存在哪里。假设我想将我的代码文件保存在 C:\Users 目录中。从这里,我正在浏览到桌面。所以,只需右键单击并在此处创建一个新文件夹。指定一个文件夹名称。所以,我的文件夹名称是“Coding Essentials for AI”。双击它。到目前为止,该文件夹似乎是空的。如果您想创建一个子文件夹,您可以继续这样做。比如,我创建一个“Module One”。双击进入。要创建新的 Jupyter Notebook,请右键单击并选择“New Notebook”选项。这将出现窗口。它会要求您选择要与 Notebook 关联的 Python 内核。所以,您可以看到我除了这个基本的 Python 3 之外没有其他内核。所以我将继续使用它。您也可以勾选此项,将 Python 3 作为您首选或默认内核启动。内核是解释您的 Python 代码并执行它的程序。您可以调整这些窗口的大小。所以,这就是您的编码窗口的样子。这是我的编码窗口。在左侧,我再次看到了我的文件浏览器窗口。您可以在此处键入您的 Python 代码。我的第一个 Python 程序,比如打印“Hello, world”。要执行此操作,您可以按 Shift+Enter 或 Ctrl+Enter。您也可以点击此按钮来执行此单元格。好的。代码写在代码单元格中。这是代码单元格,它以蓝色边界突出显示。那就是代码单元格。您可以看到它目前处于代码模式。您也可以更改单元格的模式。它目前是代码模式。我将点击此按钮。这将执行单元格。单元格执行后,单元格的输出将显示在单元格下方。这是执行单元格的一种方法。否则,如果您想从键盘操作,您可以按 Shift+Enter 或 Ctrl+Enter。Shift+Enter 将执行当前单元格并前进到下一个单元格。Ctrl+Enter 将执行当前单元格并停留在原地。现在,让我们看看另一个不需要安装并且可以从世界任何地方访问的编码环境,那就是 Google Colab。它也会在另一个浏览器窗口中打开。但您需要先登录您的 Google 帐户。所以,我们将转到 Google 并搜索 Google Colab,然后在此第一个链接上点击它。假设您已经登录了您的 Google 帐户,这将出现窗口。如果您之前打开过任何 Google Colab Notebook,它们也会显示出来。在左侧,您可以看到一个菜单,其中包含目录,一些标准的 Colab Notebooks。所以,我将点击“文件”>“新建 Notebook”。这将在您的 Google Drive 中创建一个新的 Jupyter Notebook 并将其保存。好的。您可以在顶部双击并为您的 Jupyter Notebook 提供一个名称。您的 Jupyter Notebook 将具有默认扩展名 IPYNB,即交互式 Python Notebook。同样,这仍然是您的代码块。好的,您可以键入您的 Python 代码。所以,比如这是我的第一个 Python Hello World 程序。同样,您有三种执行选项。但在那之前,在右上角,请确保您已将 Jupyter Notebook 连接到将在 Google 服务器上运行的远程 Python 内核。好的。您有很多选项,但目前我们将选择默认选项。点击“连接到新运行时”。请确保您的 Jupyter Notebook 已连接到运行时。一旦连接,它将显示一个勾号。这可能需要 15 到 20 秒才能连接。请注意,在 Google Colab 的免费帐户中,您不能同时运行多个 Colab Notebook。如果您尝试运行另一个 Colab Notebook,它会要求您关闭之前的 Notebook。这是 Google Colab 免费帐户的一个限制。正如您所见,有一个绿色的勾号,这意味着我的 Colab Notebook 已连接到远程运行时。现在我可以回到我的代码并再次执行它。同样,执行有三个选项。您可以点击此图标来执行单元格,或者您可以按 Ctrl+Enter 或 Shift+Enter。我将点击此链接,您可以看到此单元格的输出在单元格下方。好的。这就是您可以在 Colab Notebook 环境中快速创建代码的方式。如果您想知道 Notebook 保存在哪里,您可以转到“文件”>“在 Drive 中查找”。这将转到您 Google 帐户中的确切 Colab Notebooks 文件夹。现在,正如您所见,我所有的 Colab Notebooks 都位于“我的云盘/Colab Notebooks”文件夹中。好的。这是我在 Colab 中创建的 Module One Jupyter Notebook,还有一些我之前创建的其他 Notebooks。所以,这位于我的云盘/Colab Notebooks 中。所以,这就是您也可以将 Colab Notebook 上传到此特定云盘并从那里执行它们的方式。所以,比如如果您想从这里执行它,您可以右键单击任何现有 Notebook 并选择“用 Google Colab 打开”。这就是打开任何 Jupyter Notebook 的方式。一旦您将其上传到 Google Colab,右键单击并用 Google Colab 打开。这将在另一个选项卡中打开它,您可以再次连接到运行时并开始执行。那么,本视频就到这里。下次再见。谢谢。您好,欢迎回来。在本视频中,我们将深入探讨 Python 编程的一些基础概念:变量、数据类型和运算符。在本节结束时,您将理解如何声明变量,使用不同类型的数据,以及对它们执行操作。那么,让我们开始吧。让我们从变量和数据类型开始。首先,让我们谈谈 Python 中的变量和数据类型。将变量视为一个容器,用于存储信息,如数字、单词,甚至是一系列项目。Python 使处理变量非常容易。不像某些其他编程语言,您不需要显式声明它们。只需给它们一个名称并为其分配一个值,瞧,您就可以使用它们了。例如,这里我们看到不同的数据类型,如数字、字符串,甚至更复杂的数据类型,如列表和元组。这些每一种都代表 Python 可以处理的不同类型的信息。现在,让我们了解如何声明变量并为其赋值。在 Python 中,您可以通过使用等号运算符将值赋给变量来简单地声明一个变量。假设我们要将数字 50 存储在一个名为 a 的变量中。我们只需写 a = 50。就这样。无需任何额外的关键字或语句。Python 在这方面非常直观。如果您想将 a 存储在另一个变量中,我们可以这样做:b = a。这会将 a 的值赋给 b,使两个变量都包含 50。简单而有效。Python 有几种核心数据类型,您将经常使用它们。这些包括整数(用于整数)、浮点数(用于带小数的数字)、字符串(用于文本)、布尔值(表示真或假),以及 None(表示一个没有值的变量)。我们还有一些集合,如列表、元组、字典和集合,它们通常对于分组相关数据非常有用。这里您也可以看到字符串,因为在 Python 中,字符串被认为是字符的集合。理解这些数据类型将为您提供一个强大的工具箱来应对几乎任何编码问题。在为 Python 命名变量时,有一些简单的规则。首先,变量名区分大小写。因此,小写 abc 和大写 ABC 被视为不同的变量。此外,变量名必须以字母或下划线开头,绝不能以数字开头。您也可以在名称中使用数字,但它们不能放在开头。并避免使用 Python 的保留关键字,如 if、else、for、while、def、return。这些在 Python 语言中有特殊含义。例如,一个好的变量名可能是 student_score。而像 123_score 这样的名称是不允许的。牢记这些规则将有助于避免在编码时出现任何错误。现在轮到您了。让我们通过在 Jupyter Notebook 中声明和赋值一些变量来练习我们所学的知识。所以,让我们先启动 Jupyter Notebook。我将搜索 Jupyter Notebook。然后运行这个 Jupyter Notebook 应用程序。一旦启动,它将在您的默认浏览器中打开一个新的浏览器窗口。所以,您将可以访问所有这些文件夹。这通常位于您的 C:\Users 目录中。所以,这些是 C:\Users 目录中存在的所有文件夹。您可以从桌面、文档、下载等位置浏览所有文件。现在唯一的问题是我的代码文件,我下载的这个特定模块的代码文件在 D 盘的 AI Agent 和 Code Files 中。所以,首先我们必须实际浏览并更改目录到这里。好的。为此,我们将关闭它并从 Anaconda Prompt 开始。确保您选择的是 Anaconda Prompt。这与您的普通命令提示符不同。您的 Anaconda Prompt 会显示“base”字样。普通命令提示符不会显示“base”。好的,关闭它。现在,由于我的文件夹在 D 盘,我将直接先进入 D 盘,然后从那里开始我的 Jupyter Notebook。如果您不这样做,您将无法访问 D 盘文件。您只能访问 C:\Users 和用户名下的文件。按 Enter 键。这可能需要几秒钟才能打开。好的。所以,界面仍然相同。只是我使用的技术略有不同,这样我就可以访问我保存在所需目录中的实际代码文件。所以,您可以看到这是 D 盘中存在的文件夹。所以,这就是我的 AI Agent 代码文件所在的位置。好的。现在您可以看到这个特定模块的所有 Jupyter Notebooks。我将双击第一个,即“在 Python 中实现变量和数据类型”。所以,让我们开始吧。好的。所以,您可以通过使用此按钮或点击此按钮来执行所有代码,即运行按钮。或者您可以使用键盘快捷键,即 Shift+Enter 或 Ctrl+Enter。我将使用这个键盘快捷键 Shift+Enter。所以,让我定义一个变量名 a 并为其赋值为 5。我怎么知道值已分配?让我们打印变量的值。当我通过 Shift+Enter 执行此单元格时,我得到的 a 的值是 5。这样,您可以定义任何变量名,并使用等号运算符为其赋值。好的。您还可以使用 print 函数打印变量的值。您可以看到 print a 返回 5。好的。这里我定义 a = 7,并创建另一个变量 b,将值赋回给 a,然后将 a 的值从 7 更改为 3。让我们看看会发生什么。那么,a 的值现在是多少?由于 a 的值已从 a = 7 更改为 a = 3,因此它应该返回 a = 3。完美。由于 b 在 a 的值为 7 时被赋值为 a,因此 b 仍应指向 a 的原始值,即 7。太棒了。变量在 Python 中就是这样工作的。现在我们已经讨论了演示文稿中的变量命名规则。所以,这里快速回顾一下这些规则。Python 变量名区分大小写,这意味着小写 a 和大写 A 是不同的。标识符或变量名可以是字母(小写或大写)和数字的组合。您甚至可以使用下划线。您可以在开头或结尾使用下划线。所以,这些都是有效的变量名。您不能使用以数字开头的变量名。例如,1_variable 是无效的,但 variable_1 是完全可以的。所以,让我们看看,最后,您也不能使用关键字作为变量名,因为关键字是保留的。因此,如果您尝试为这些关键字中的任何一个赋值,Python 将会抛出错误。所以,我定义了,比如 a = 400,小写 a = 400,大写 a = 4。让我们看看会发生什么。所以,您可以看到小写 a 仍然指向 400,大写 a 指向 4。所以,让我们快速验证一些规则。所以,_a 是有效的。好的。但如果您说 a_,那也是有效的。好的。因为下划线是可以接受的。但如果您在开头或结尾有任何其他特殊字符,那将是无效的。好的,您可以看到这是一个语法错误消息。当您尝试定义 1a 为 5 时,您会得到相同的语法错误。如果您尝试定义 a1 为 5 或 500 无论数字是多少,那都是完全可以的。现在我们将进入数据类型部分。让我们创建一些不同数据类型的变量。这里我将 a 创建为一个整数。我们可以使用 type 函数检查数据类型。type 是一个内置的 Python 函数,用于检查任何 Python 对象的数据类型。所以,您可以看到分配给 a 的数据类型是整数。同样,让我创建一个字符串数据类型。所以,b 是“luxe”。您可以看到字符串是通过使用双引号创建的。您也可以使用单引号创建字符串。所以,b 的数据类型是字符串。对于浮点数,您可以直接赋值。只需确保您有一个小数点。所以,这里分配给 c 的值是 5.55,您可以看到数据类型是浮点数,布尔值可以是 True 或 False。好的。所以,您可以看到数据类型,比如 E 是 False。所以,D 和 E 都是布尔值。如果您有兴趣查看当前命名空间中存在哪些变量,只需键入 `whos`,您就可以看到所有这些变量都存在于当前命名空间中。好的,您可以使用所有这些变量进行计算。所以,让我们进行一些快速的数据类型转换。让我将浮点数转换为整数。所以,我的年龄是 26.3333...。我使用 int 函数将该年龄转换为整数。int 用于将浮点数类型转换为整数。好的。所以,您可以看到 26.333 已转换为整数。此函数的作用是简单地忽略小数点以及小数点之后的所有内容。它只取浮点数的整数部分。同样,我也可以将字符串转换为整数。所以,如果我尝试将字符串添加到整数,这将导致错误。所以,这是一个单引号字符串,这是一个整数。所以,您不能将字符串添加到整数。此操作将导致错误。您可以看到。但是,如果我将这个“2”从字符串转换为整数,我将这个“2”从字符串转换为整数,我仍然可以将其与整数 6 相加。好的,让我们这样做,完美,这就是它的工作方式。这里“2”字符串被转换为整数,然后这变成整数,这已经是整数,所以发生整数加法,最终返回的也是整数。您可以检查我的 int 的数据类型也是整数。我将在演示文稿中再见,我们将继续讨论 Python 中的运算符。在 Python 中,运算符是执行变量和值运算的符号。这些包括加法、乘法、除法等算术运算。将运算符视为工具箱中的工具。它们帮助您操作存储在变量中的数据。例如,如果您想将两个数字相加,您将使用加号运算符。很简单,对吧?操作数是运算符应用的 on 的值。Python 提供了几种类型的运算符。用于基本数学的算术运算符。用于比较值的比较运算符,如大于或等于。用于组合多个条件的逻辑运算符。用于处理位的按位运算符。用于赋值的赋值运算符。用于检查两个变量是否引用同一对象的身份运算符。这些运算符使我们能够执行复杂的计算,并使我们的代码更加强大。例如,您可以使用比较运算符检查学生分数是否大于 50,然后使用逻辑运算符决定下一步做什么。现在是时候练习使用运算符了。让我们打开我们的 Python 编辑器并尝试一些算术和比较运算。所以,我们已经学习了变量和数据类型的概念。现在,我们将继续讨论 Python 中的运算符。我将双击此文件并打开它。所以,正如我们已经看到的,Python 中有不同类型的运算符。用于数学计算的算术运算符,比较运算符,逻辑运算符,按位运算符等等。让我们尝试一些这些运算符。所以,这里我创建了四个变量。A 的值为 15,这是一个整数。B 的值也是 8,仍然是整数。C 的值为 15.5。C 将是一个浮点数。S 是“hello”,用单引号。这是一个字符串。所以,让我执行它。好的。所以,这些是 Python 中最常见的算术运算符。+ 用于加法,- 用于减法。这是星号 *,用于两个数字的乘法。这是用于两个数字的除法。这是模运算符 %。它将给出除法后的余数。对于指数运算,您可以使用两个星号 **。好的。这是用于浮点除法。浮点除法通常给出除法后的商。所以,让我们看看 a 和 b 的加法。我从 b 中减去 a。所以,让我们看看其中一些运算符的实际应用。所以,我将 a 和 b 相加。现在,我从 a 中减去 b。所以,我将 a 除以 b。所以,我们已经看到 a 是 15,b 是 8。所以,这是 15 除以 8。这是 15 * 8 = 120。这是指数运算。所以,2 的 2 次方是 8。同样,您可以更改此数字。2 的 10 次方是 1024。所以,这是指数或幂运算。这是浮点除法。所以,这是 15 除以 8。您只关注商部分,即 1。模运算符将给出余数。所以,余数应该是 7。所以,当 15 除以 8 时,您将得到 1 作为商,7 作为余数。让我们看看一些比较运算符。所以,两个等号 == 用于检查两个操作数之间的相等性。这是不等于 !=。这是大于 >。这是小于 <,小于等于 <=,以及大于等于 >=。所以,在继续之前,我将打印 a 和 b 的值。所以,a 是 15,b 是 8。我正在检查 a 是否等于 b。它显示为 False。当然,a 不等于 b,因为 a 是 15,b 是 8。现在我正在检查 a 是否等于 51。所以,a 不等于 51,因为 a 实际上等于 15。所以,这里我正在检查 a 是否等于 b 或不等于 b,并检查返回输出的数据类型。这里输出将是一个布尔值,您可以看到。所以,对于所有这些比较运算符,返回的输出将是布尔类型。您可以看到 True、False、True、False。所以,True Falsebasically是布尔数据类型。现在我正在检查 a 是否大于 b。是的,它确实大于 b。a 小于 b。这应该返回 False。a 大于 51。不,15 小于 51。所以,再次为 False。现在对于逻辑运算符,and、or 和 not。所以,1 等于 1 吗?这将返回 True。2 等于 2 吗?是的,这也将返回 True。所以,如果这个为 True,这个也为 True,那么净结果将是 True。所以,True and True 将返回 True。这是 True。这是 False。所以,True or False 将再次返回 True。这就是 or 运算符的真值表的工作方式。所以,and 运算符只有在两者都为 True 时才返回 True。如果其中任何一个为 False。好的,让我说清楚。所以,让我们将其设为 20。所以,这是 True,但这是 False。对吧?所以,这将返回 False。所以,and 运算符只有在两个条件都返回 True 时才返回 True。同时,如果其中任何一个或两个都为 False,那么净返回输出将为 False。您可以在这里看到。好的。所以,这会回到 True。但在或操作的情况下,我再次检查两个条件。所以,如果其中任何一个为 True,它将返回 True。所以,这是 True。这是 False,但仍然返回 True。好的。但如果两者都为 False,比如现在是 10。好的。所以,10 不等于 10。所以,这是 False。3 不等于 4。这也为 False。所以,False or False 将返回 False。如果其中任何一个为 True,它将返回 True。您可以看到。好的。现在您可以进行更复杂的复合操作。好的。所以,您可以关注括号。所以,我首先检查此括号内的条件,然后我将其与此条件的或操作进行复合。好的。所以,我们首先检查 2 是否大于 3。这将返回 False。这将返回 True。所以,False or True 将返回 True。所以,从这里到这里的输出将是 True。现在这是 True,而这已经是 True。所以,净结果应该是 True。这个编码练习就到这里。我将在下一部分再见。您好,欢迎回来。在本视频中,我们将探讨条件语句,这是 Python 中一个基本概念,它帮助我们在代码中做出决策。如果您曾经想知道程序如何根据不同的输入或条件知道该做什么,那么就是这个了。让我们开始吧。条件语句帮助我们在代码中做出决策。想象一下您下班回家。如果您准时到家,您可能会做晚饭,但如果您迟到了,您可能只会点外卖。这种决策正是条件语句允许我们在 Python 中建模的方式。我们使用条件语句来实现各种目的,例如做出决策、控制程序流程、验证输入,甚至优雅地处理错误。它们是任何需要适应不同情况的程序的支柱。让我们分解一个场景。想象一下。您到家了。这是我们的事件。现在,有两种可能的情况。您准时到家,或者您迟到了。如果您准时,您决定做晚饭。但如果您迟到了,您决定点外卖。这正是 Python 中的条件语句所做的。我们设置条件,根据它们是 True 还是 False,我们确定要采取的适当操作。这就像一个决策流程图。非常直观,对吧?Python 为我们提供了几种条件语句。简单的 if 语句仅在条件为 True 时执行代码。if else 语句用于指定在条件为 False 时应发生什么。if elif else 语句用于按顺序处理多个条件。最后是嵌套 if 语句,其中一个 if 语句嵌套在另一个 if 语句中。这些不同类型的条件语句允许我们编写复杂的决策逻辑。这里快速看一下一些伪代码,以帮助理解我们如何编写条件语句。如果我们的条件是到达时间晚于晚上 10 点,我们决定点外卖。如果早于此,我们则做饭。此伪代码代表了决策过程。使用这种简单的伪代码有助于我们在跳入实际 Python 代码之前思考逻辑,从而更容易规划程序需要做什么。让我们看一下实际的 Python 语法。对于单个条件,我们使用 if 关键字后跟一个冒号。在 if 条件为 True 时运行的代码块在下方缩进。例如,如果您有一个变量 x,并且想检查它是否为正数,您将编写 `if x > 0:` 然后是四个空格的缩进 `print("Positive")`。所以,Python 语法非常简单易懂。只需记住缩进是关键。当有多个条件时,您可以使用 elif 和 else。这是一个简单的例子。假设您有一个变量 x。如果 x 大于 0,您将打印“Positive”。如果 x 等于 0,您将打印“Zero”。否则,您将打印“Negative”。使用 if、elif、else 有助于使我们的代码可读且逻辑上组织良好。它允许我们高效地处理多种可能性,而不是使用大量独立的 if 语句。现在,是时候进行一些实践了。让我们打开我们的 Python 环境并尝试编写一些条件语句。在结束之前,让我们谈谈一些最佳实践。首先,始终尝试编写清晰易懂的条件。适当的缩进在 Python 中至关重要。它定义了哪些代码属于哪个条件。尽量避免深度嵌套条件,因为这会使您的代码难以阅读。相反,使用逻辑运算符或重构代码。最后,请记住使用注释来解释任何复杂的条件。这将有助于任何阅读您代码的人,包括您未来的自己。遵循这些最佳实践将有助于使您的代码更易于维护,并且更容易被他人理解。所以,在开始条件语句之前,让我们快速看一下 Python 中的缩进和注释。所以,缩进意味着在任何语句的开头提供空格和制表符。因此,具有相同缩进的这些语句将属于同一组。所以,在这段代码中,我定义了 a = 5,然后 b = 6,但这里我有一个缩进,一个制表符。一个制表符相当于四个空格。通常您可以在文本编辑器的设置中看到这一点,缩进默认是四个空格。所以,您可以看到这里有四个空格 1、2、3 和 4。这里不期望缩进,这会导致错误。为什么不期望?因为缩进通常在控制结构中预期,如 if else 语句、try catch 语句、for 和 while 循环、函数和类定义等。这里您有 if else 语句。所以我正在检查 2 是否等于 20。这将返回 False。所以我可以将其更改为 2。现在我正在检查 2 是否等于 2。这将使其为 True。所以,如果为 True,意味着我进入了 if 条件。这将打印此打印语句。正确。但如果我忘记了缩进。让我们看看会发生什么。它说“缩进错误,在 if 语句后期望一个缩进的代码块”。所以,请记住,每当您使用 if 语句或任何循环和函数定义时,从第一行开始的所有内容都必须缩进。好的。所以,这里缩进是强制性的。这有助于 Python 知道当此条件为 True 时必须执行此语句。好的。现在您可以使用井号 # 在您想要放置注释的地方编写注释。好的。您可以从代码行的末尾开始注释,也可以从行的开头开始注释。好的。所以,当我执行这段代码时,这一行被执行。这一行被注释掉了。好的。所以,让我取消注释。所以我删除了这个井号。然后我再次执行。所以,当我再次执行它时,您可以看到我也得到了这里的打印语句,以及这个。这之前被注释掉了。所以,第二行没有出现在输出中。好的。现在我可以重复它。所以我注释掉了第一行,并再次执行这段代码。您可以看到,由于第一行被注释掉了,因此它没有被执行,只有这一行被执行。好的。所以,这样您就可以在代码块中编写多行代码,并选择要注释掉或取消注释的行。在 Windows 系统上,注释和取消注释的键盘快捷键是按住 Ctrl 键和反斜杠键。好的。所以,无论您将光标放在哪一行,您想要注释或取消注释。好的。然后只需按 Ctrl 和斜杠,它就会被注释掉。再次,如果您执行相同的操作,Ctrl 和斜杠,它将被取消注释。好的。现在,让我们检查一些条件语句。好的,我们已经看过了。所以,这里我将使用 if 语句。我将 x 赋值为 1,并检查 x 是否等于 1。让我们看看。是的,确实 x 等于 1。所以,它进入了 if 条件内部,并且执行了此打印语句。现在,由于 x 已经等于 1,我正在检查 x 是否等于 3。所以,您现在应该知道这会返回 False。由于它返回 False,因此此打印语句将不会执行。所以,这里什么也没发生。现在我有一个 a = 5 和 b = 10。我正在检查 a 是否大于 b。所以,5 是否大于 10?不。所以,它转到 else。好的?因为这是 False。所以,这个语句没有被执行。所以,控制自动转到 else。再次重复,如果这是 True,将执行此语句。如果此条件为 False,控制将自动转到 else 块。所以,else 块包含此打印语句,因此下一个打印语句将被执行。您也可以检查多个条件。所以,这里 a 是 8,b 是 10。我正在检查 a 是否大于 10,以及 b 是否大于 10。所以,您可以说这是一个复合条件。所以,正在检查两个条件。所以,这个 if 只有在两个语句都为 True 时才为 True,因为有 and 运算符。好的。所以,True and True 将使 if 条件为 True。elif,我正在检查 a 是否大于 5,并且 b 是否也大于 5。所以,如果这是 True,并且这也很 True,那么这将打印出来。好的。否则,如果这些都没有执行,那么控制将自动转到 else。让我们看看。完美。所以,这里满足了这个条件。看起来这个条件得到了满足。现在我正在使用 input 函数获取用户输入。好的。所以,用户输入以字符串形式进入 x。我需要将其转换为整数。好的。所以,默认情况下,input 函数的输出将是一个字符串。我需要将其类型转换为整数。所以,现在 x 被替换了。最初您的 x 是一个字符串。现在在第二行中,它被替换为整数。现在我将其除以 2 并检查余数。余数是否等于 0?好的。这是一个模运算符。所以,模运算符将给出除法后的余数。好的。所以,除法后的余数被检查是否为零。如果除以 2 的余数为零,则表示该数字是偶数。所以,我在这里检查用户输入的数字是偶数还是奇数。很简单。所以,让我输入一个数字。比如 15。所以,15 除以 2。您可以手动检查,15 模 2 不会得到 0。所以,1 不等于 0。所以,if 条件不满足。所以,控制自动转到 else,因此打印了“Odd”。现在我再次运行它。让我输入一个大数字。无论多大都没关系。这个数字除以 2 的余数为零,因此打印了与“Even”对应的打印语句。现在,在第二个问题中,我将获取用户输入并将其分配给另一个变量 y。好的,默认情况下,这个 y 仍然是字符串格式。我需要将其转换为整数,然后我需要根据用户提供的分数打印等级,是 A、B 还是 F。所以,如果分数大于 90。如果数字大于 90,那么我将分配 A 级。如果数字大于 60,我将分配 B 级,否则学生不及格。所以,让我输入一个数字。比如 95。好的,太棒了。我得到了 A 级。让我用另一个数字重新运行它。比如 72。所以,这里发生了什么?首先检查 y 是否大于 90。所以,现在您的 y 是 72。72 当然不大于 90。所以,这个条件不满足。所以,控制自动转到 elif。所以,现在检查这个条件:72 是否大于 60。是的。所以,这个打印语句被执行,程序停止。好的。所以,这三个语句中只有一个会执行。这三个中只有一个会执行。如果这是 True,将执行此语句并停止。如果这不是 True,那么它将检查这是否为 True。如果这是 True,将执行此语句并停止。如果两者都不是 True,那么控制将自动转到最后的 else 语句,并且总是打印这个。所以,如果您愿意,您可以再次用另一个数字 45 来检查。是的,45 是不及格的等级。我很高兴欢迎您观看关于 Python 循环构造的视频。循环非常强大。它们使我们能够高效地重复任务,而无需编写大量重复的代码。今天我们将学习如何让我们的代码更智能、更高效、更容易管理。让我们开始吧。那么,Python 中的循环构造究竟是什么呢?它们是允许我们在特定条件满足时重复一段代码的工具。将其想象成一个指令,说“继续这样做,直到我告诉你停止”。这可以帮助我们自动化重复任务,更轻松地处理数据,并用更少的代码行解决复杂问题。让我给您一个简单的场景。想象一下 Jake 想打印他的名字 10 次。现在,他可以写 10 次 `print("Jake")`,但这很乏味,对吧?这就是循环派上用场的地方。与其一遍又一遍地编写相同的代码,我们可以使用循环来为我们完成这项工作。使用循环,我们只需几行代码就可以告诉 Python 打印 Jake 的名字 10 次。这使我们的工作更快、更容易、更优雅。那么,什么时候使用循环呢?嗯,在几种情况下,循环非常有用。首先,重复性任务,就像我们打印名字多次的例子。接下来,处理用户输入,当您想一直提问直到获得有效答案时。迭代数据结构,如列表或字典。条件重复,当您一直执行某项操作直到满足某个条件时。甚至模拟或游戏,其中重复操作是某些体验的一部分。循环可以为我们节省大量时间,尤其是在我们的任务不断增加时。让我们仔细看看 Python 中的循环类型。在 Python 中,我们有两种主要的循环类型:while 循环和 for 循环。首先,我们将讨论 while 循环。当您不知道需要重复任务的确切次数时,使用 while 循环。它会一直运行,直到条件不再满足为止。例如,您可以使用 while 循环向用户请求输入,直到他们提供有效答案为止。接下来,我们有 for 循环。当您确切知道需要重复某项操作的次数时,可以使用它。它非常适合迭代序列,如数字列表或项目集。它是可预测的,非常适合您知道需要多少次迭代的情况。让我们多谈谈 while 循环。例如,我们想一直询问用户的年龄,直到他们提供一个有效的数字。while 循环是最佳选择。它会一直重复,直到条件变为 False,然后停止。当您需要重复一项任务未知次数时,它非常适合。while 循环就像说“只要条件为 True,就继续重复这段代码块”。现在让我们继续 for 循环。for 循环用于迭代序列,无论是列表、字符串,甚至是数字范围。当您确切知道需要重复某项操作的次数时,它非常有用。将 for 循环视为
逐一完成待办事项列表。你处理每一项,直到全部完成。无论是遍历 1 到 10 的数字,还是打印列表中的每个项目,for 循环都是完美的工具。我们还有嵌套循环,即循环内部的循环。当我们需要处理多维数据时,通常会使用它们。想象一下,你有一个像表格中的行和列一样的数值网格。你可以使用嵌套循环遍历每一行,并在每一行中访问每一列。尽管功能强大,但嵌套循环可能有点棘手,在使用它们时要小心很重要。过多的嵌套循环会使你的代码更难阅读。所以,要明智地使用它们。好了,理论够了。是时候进行一些实际编码了。让我们打开我们的 Python 环境,练习 while 循环和 for 循环。感谢你加入我关于循环结构的视频。我希望你现在对循环以及它们如何简化你的代码感到更自在。在下一节中,我们将继续构建这些概念,使我们的程序更具动态性和交互性。所以,让我们从打开 Anaconda prompt 开始。所以,从 Anaconda prompt,让我浏览到存放文件的目录。好的。从这里,Jupiter notebook。好的。所以我的 Jupyter notebook 已经启动并运行。我在这里有我的代码文件,模块一,在这个视频中我们将继续学习循环结构。好的,在这个编码教程中,我们将看看如何使用 for 和 while 循环。所以,让我们先从 for 循环开始。所以,当我们想运行一段代码特定次数时,我们会使用 for 循环。所以,你已经清楚你将运行你的代码块一些特定的次数,那么 for 循环是最佳选择。好的。所以,这是一个简单的例子:for number in range(4)。所以,range 实际上是一个生成器函数。它将创建从零到停止数字减一的索引。所以,它将创建索引 0、1、2 和 3。所以,本质上,在第一次迭代中,这个数字将取值为零。然后在下一次迭代中,这个数字将取值为 1,然后是 2,然后是 3。它将在停止索引之前停止。好的。所以,让我们打印出来看看。所以,本质上,我运行这个 for 循环四次。这正是这个 for 循环语句所说的。我想运行一个 for 循环四次迭代。所以,这个数字将从 range 生成器中获取值。好的。现在,假设你不想从零开始。你想从另一个数字开始。假设在这种情况下是 1。然后你可以给 range 函数提供两个参数。第一个参数是你的起始点,第二个参数是结束点。一如既往,请记住,一旦 range 值达到停止点之前一个,数字就会停止或迭代就会停止。所以,这次它将从 1 到 4。好的?因为起始数字是 1,结束数字是 5。所以,它将在之前停止。你也可以使用步长。所以,在这种情况下,我提供了我的起始数字、结束数字,这是我的步长。所以,步长默认为 1。这里我将其增加到 2,这意味着给我从 1 到 9 的所有数字。它将在 10 之前停止。所以,它将是 1 到 9。给我从 1 到 9 的所有数字,跳过每隔一个数字。所以,你想要每隔一个数字。好的。所以,让我们看看。所以,1、2、3、5、7 和 9。是的。所以,你在最后打印数字,你在打印一个空格,一个空白字符,这就是它没有一个接一个地出现的真正原因,它在这里是默认的 end 是反斜杠 n,它基本上是一个换行符,那是默认的 end,你已经将其更改为一个空格,这就是为什么后续的迭代打印在同一行上。现在,我想使用 for 循环迭代一个字符串。如果你还记得在第一个视频中,我们已经看到字符串本质上也是一个集合。它是一组字符。好的,它也是一个集合。所以,这里我说的是 for character in analytics with okay,我想获取每一个字符并打印它们。完美。所以,在第一次迭代中,a 被获取,在下一次迭代中,n 被获取,依此类推。所以,一个接一个地获取每个字符并打印。好的。而且,如果你想在这里使用 end,你可以随时使用 end。所以我将重新运行它,你可以看到。好的,现在是嵌套 for 循环。所以,嵌套 for 循环就是循环内部的循环。好的。所以,将有一个外部循环和一个内部循环。好的。所以,如果你看到缩进,好的,那么整个循环都缩进在外部循环内。好的。而这个语句缩进在内部循环内。所以,它将在内部循环的每一次迭代中执行。而对于外部循环的每一次迭代,整个事情都将执行。好的。所以,让我们看看它做了什么。在外部循环中,我正在迭代数字 1 和 2。它将在 3 之前停止。所以,它将从 1 开始,在 2 停止。现在,内部循环将获取 ABC 中的字符。好的。所以,在第一次迭代中,内部循环字符将是 A。下一次迭代将是 B。下一次迭代将是 C。好的。所以,在这里,在外部循环的第一次迭代中,这将是 1,然后这将是 A,然后是 1 B,然后是 1 C,然后它将自动从 2 A 开始,然后是 2 B,然后是 2 C,它将是这样。让我们看看。完美。所以,这三个 1 是由于内部循环 A、B 和 C 的执行而出现的,然后外部循环自动增量到 2。默认增量是 1,我们已经看到了。是的,完美。现在是 while 循环。所以,这里,假设你想执行一段代码,而无需最初指定你想执行多少次。你只需继续执行,直到满足某个条件。所以,只要 while 条件设置为 true,while 循环中的代码就会继续执行。好的,让我们看看。所以,在下面的例子中,我们已经将一个变量初始化为零,我们想增加它的值,并且循环将继续运行,只有当值小于 7 时。好的。所以,这里我有一个 number 等于零,并且每次在执行这些语句之前,好的,在进入循环之前,我将检查这个数字的值是否小于 7。好的。所以,假设我从 10 开始并执行它。这个数字已经是 10 了。好的。所以,发生了什么?while 循环条件本身就变为 false,因此这些 print 语句和增量不会执行。让我们看看,什么都没发生。我在这里没有得到任何输出打印。好的。现在,让我回到 1 并再次执行它。所以,第一次迭代中的数字是 1。它小于 7。所以,它进入了 while 循环。它打印数字,然后在其下一行中增加它。好的。数字被增加了。所以,它变成 2。所以,在下一次迭代中,这是 2。打印 2,然后它增加到 3。在下一次迭代中,这已经是 3。所以,3 小于 7。再次为 true。所以,它打印 3。好的。然后增加到 4。4 已经小于 7。所以,它打印 4,然后它增加到 5,然后到 6,然后到 7。所以,当它增加到 7 时。现在 7 不小于 7。所以,会发生什么?while 循环条件变为 false,因此什么都不会执行。while 循环会自行优雅地退出。是的。所以,只要这个条件变为 false,while 循环就会自行退出。好的。所以,这里我增加了 22。所以,这将跳到 2 个单位。所以,同样的事情,只是 while 循环终止得更快。现在,现在,假设你不想继续所有迭代。好的,你想在迭代之间跳转,或者你想跳过中间的迭代。好的。或者你想根据某个条件跳出 while 循环甚至 for 循环。好的,你想根据某个条件跳出循环,或者你想跳过一些迭代。你不想完成该迭代。你想根据某个条件继续到下一次迭代。这正是我们接下来要看到的。好的。所以,一些外部因素可能会影响你的程序,当这种情况发生时,你可能希望程序完全退出循环,或者在继续和忽略之前跳过循环的一部分。所以,让我们先看看 break 语句。所以,break 语句提供了一个机会,当满足某个条件时退出循环。好的,让我们看看。所以,在这种情况下,我将数字再次初始化为零。我将逐一增加这个数字,直到 9。范围从零开始,直到 9。所以,由于 range 生成器函数,range 值将自动增加。当数字等于 5 时,我想跳出循环。所以,for 循环被强制中断。好的。所以,让我执行它。你可以看到数字是 0、1、2、3、4。在下一次迭代中,好的,数字是 5。当它等于 5 时,好的,这个条件变为 true。所以,它跳出了循环。好的。并且一旦它跳出循环,它就不会被执行。所以,请记住这一点。break 下方的任何 Python 语句都将永远不会被执行。好的,在 break 下方并且是循环的一部分。好的,现在这个 print 不是 for 循环的一部分。所以,它被执行了。所以,break 下方并且是主循环一部分的任何语句都不会被执行。这个 print 在 for 循环之外。所以,它被执行了。让我们再举一个例子。所以,这里将要求用户输入一个密码,该密码已设置为 data,如果密码匹配,它将打印欢迎来到 Python 课程,否则它将打印密码错误。好的。所以,用户将有四次尝试。好的。所以,呃,试用次数 1、2、3 和 4。好的。当达到第四次试用时,它会警告你这是你的最后一次试用。好的。而且,一如既往,它会不断要求输入密码,并且如果密码在任何一次迭代中匹配,它将简单地打印欢迎来到课程并跳出循环。所以,现在这个 break 甚至可以在第一次迭代中执行,如果密码匹配。如果密码不匹配,那么 else 条件将被执行,它将通知用户输入的密码是错误的,并自动继续下一次迭代。是的,有道理。所以,让我执行它。所以,输入密码。所以我写了 1 2 3 4 5 这个。所以,这又是错的。所以我必须输入 ABC,这也是错的。所以,现在只剩一次试用了。好的。所以,让我试试 hello。所以,在所有四次迭代中,我都输入了错误的密码。好的。所以,这里设置了四次迭代。所以,所有四次迭代都完成了。它只是打印密码错误,for 循环就结束了。现在,让我再次用正确的密码执行它。这次它告诉我欢迎来到 Python 课程。所以,这里输入的密码是正确的。所以,它跳出了循环,不再进行任何迭代。好的。所以,还剩下两次迭代。第一次迭代我输入了这个。第二次迭代我输入了这个。所以,还剩下两次迭代,但它跳出了 for 循环。现在,让我们看看 continue 语句。这为你提供了一个选项,可以在触发某个条件时跳过循环的一部分。好的,让我们看看。所以,我再次将数字初始化为零。我将进行 10 次迭代,从 0 到 9。如果数字是 5,则跳过该数字。所以,continue 意味着跳过这次执行,并继续下一次迭代。好的,这就是它的意思。所以,与 break 语句类似,continue 下方并且是 for 循环或 while 循环一部分的任何语句都不会被执行。所以,迭代将从这一点继续。控制将从这里回到第一行。好的。所以,continue 下方的这一行将不会被执行,但迭代会继续。好的。这正是 continue 语句的意思。它说在那里继续到下一次迭代。好的,不要执行这个,然后继续到下一次迭代。好的。当数字等于 5 时。让我们看看。所以,数字是 0、1、2、3、4,如果你在这里看到,数字 5 没有被打印,因为发生了什么?当数字等于 5 时,我们立即继续了迭代。所以,这个 print 语句没有被触发。好的,这里是另一个例子。好的。用户将被要求输入一个密码,该密码设置为 OTP 值,即 1 2 32。如果 OTP 正确,用户将被要求输入姓名和城市。好的。而且,一如既往,用户将有四次尝试,从 1 到 4。好的。所以,如果有四次尝试,当试用次数等于 4 时,也就是说,当用户只剩最后一次试用时,将显示此内容,并且每次都会要求用户输入 OTP。好的。所以,让我输入一些 OTP。所以,它说请重试,因为输入的 OTP 不等于设置为 1 2 32 的 OTP。所以,它告诉用户重试并继续下一次迭代。所以,从这里开始,控制就进入了主 for 循环。好的。从这里开始,控制就进入了主 for 循环。就是这样。所以,没有检查 else 条件。好的。不检查 else 条件。所以,假设 1 2 3。现在你看到我输入的 OTP 等于 OTP。所以,在这种情况下,控制自动转到 else,因为这里的 if 将返回 false。由于它返回 false,控制转到 else,现在它要求我输入我的名字。所以我只是输入我的名字和城市。完成。完美。所以,continue 语句与 break 语句的主要区别在于,当变量被评估并等于 5 时,我们的代码将继续进行,尽管存在中断。对?好的,最后,我们来到 pass 语句。Pass 基本上是一个空操作。它是一个有效的 Python 语句,不执行任何操作。好的,这就是它的意思。所以,数字再次设置为零,这个数字将从 0 到 9。好的。如果数字是 5,什么也不做。Pass 说什么也不做。如果你比如说注释掉这个语句,它会抛出一个错误,因为在 if 条件下,没有执行任何有效的 Python 语句。好的。现在,这个 print 是 for 循环的一部分。它不是 if 条件的一部分,因为它与它在同一级别缩进。现在,这个缩进在 if 中的 pass 实际上是 if 条件的一部分。好的。所以,这正是用例。好的,缩进错误。所以,如果我没有有效的 Python 语句,它可以是任何东西,比如一个简单的 print 语句,这将起作用。好的,让我。是的,这将起作用。但是,假设如果我没有给出任何有效的 Python 语句,这仍然会给我一个错误。好的。所以,假设我不想在满足此条件时执行任何操作。也许我想明天写代码,或者在与同事讨论之后。好的。当数字等于 5 时,到底该做什么?现在我没有答案。假设在一个简单的示例场景中。所以,你创建了一个占位符。好的,如果数字是 5,就做某事。但是到底是什么?你不知道,你不想指定,你不想立即写下代码。所以,只需 pass。好的。所以,这成为一个有效的 Python 语句,迭代继续。这正是 pass 的目的。你可以将 pass 语句与循环、任何循环、if 条件一起使用。你可以在 try except 块、函数定义、类定义中使用它。任何你想创建空 Python 结构而不指定代码行的地方,你都可以使用 pass。函数是你可以在代码中使用的最强大的工具之一,它允许你重用代码块,使你的程序更有条理,更容易维护。在本课程结束时,你将能够舒适地定义自己的函数,使用内置函数,甚至使用 Lambda 函数。让我们开始吧。那么,为什么函数很重要?想象一下,你必须烤饼干,每次你这样做,你都必须从头开始测量所有配料。相反,难道不只是有一个食谱会更容易吗?函数就像编程中的食谱。它们允许你为特定任务编写一次代码,然后在需要时重用它。这为你节省了时间,也有助于避免错误。让我们看一个场景。假设 Anna 想向 50 个人发送个性化的问候消息。她需要确保每条消息都是一致的,除了收件人的姓名。一种方法是为每个人写出消息,但这有很多重复的工作,而且很容易出错。相反,我们可以使用一个函数来处理这项任务。通过定义一个 greeting 函数,Anna 可以简单地为每个收件人调用该函数并自动个性化消息。这使得代码效率更高,并防止错误。让我们分解一下函数是什么。在 Python 中,函数是一段执行特定任务的代码块。你通过使用 def 关键字,后跟函数名、输入参数以及函数内部应运行的代码来定义函数。这是一个简单的例子。让我们定义一个名为 greet 的函数,它接受一个名字作为参数并打印问候语。在这个例子中,greet Anna 将打印 hello Anna, how are you today? 定义后,我们可以根据需要多次调用此函数,从而避免每次都输入问候语。Python 提供了几种类型的函数。例如,内置函数如 print、length 和 sum。用户定义的函数,你可以自己创建以执行自定义任务。Lambda 函数,它们是用于简单任务的小型单行函数。Python 提供了许多非常有用的内置函数。你无需导入任何内容即可使用它们。它们随时可用。一些常见的例子包括用于输入输出的函数,如 input 和 print。用于数据类型转换的函数,如 int、float、string,这些函数允许你在不同数据类型之间进行转换。数学函数,如 sum、max、abs。这些有助于基本计算。例如,如果你想找出列表中最大的数字,你可以简单地使用 max,然后它将返回一个数字。还有其他非常重要的函数,如 length、range 和 type。让我们转向用户定义的函数。这些是你创建的用于在自己的程序中执行特定任务的函数。要创建用户定义的函数,你使用 def 关键字,后跟函数名、参数和代码块。假设你正在创建一个程序来问候用户。只需编写一个函数,然后使用用户名调用该函数。就是这么简单。接下来,我们有 lambda 函数。Lambda 函数是小型匿名函数,通常用于简单任务。它们使用 lambda 关键字定义,并且只能包含一个表达式。Lambda 函数经常与 map、filter 和 sorted 等函数一起使用。例如,如果你有一个数字列表,并且你想只过滤出偶数,lambda 函数可以使这变得非常容易。是时候将我们学到的知识付诸实践了。让我们在 Python 中编写一些函数。感谢你加入我关于 Python 函数的课程。我希望你现在能看到函数对于使你的代码更高效、更有条理是多么强大和有用。现在,让我们看看如何在 Python 中创建函数。正如已经讨论过的,函数的作用是分组需要多次执行的代码行或几行代码。所以,我们将使用 def 关键字来创建函数定义,后面应该跟着函数名。所以,这里 def 用于创建函数。这里的函数名是 welcome。所以,这个函数做什么?它将打印欢迎来到 Python 课程。所以,让我在这里创建函数。现在调用函数很简单。你只需要取函数名,后跟括号。所以,让我在这里调用函数。所以,它打印欢迎来到 Python 课程。我再次调用函数。它再次打印。所以,我调用的次数越多。好的,它将执行函数定义内的所有代码行,依此类推。现在,我在这里创建另一个函数,它将添加两个数字。好的,这两个数字已经设置为 3 和 4,总和是 3 + 4 = 7,它将打印总和。所以,让我创建函数并创建另一个函数。我们将看到这两个函数之间的区别。所以,让我执行函数。你可以看到 print 语句是从这里执行的,总和打印为 7。好的,你可以更改这些数字看看。呃,这是 30 + 4。所以,这将变成 34。好的,现在我将此函数的输出分配给一个变量。好的,让我打印输出的值。它不打印任何东西。好的,让我看看这个输出的数据类型。它说 none。所以,基本上,似乎没有任何东西存储在 output one 中,这就是为什么输出数据类型是 none。所以,这里没有存储任何东西。它是一个空指针。本质上,这是一个空指针。这里没有存储任何东西。所以,我稍微修改了主函数以返回总和的值。这是额外的代码。所以,直到这里都是一样的。这是额外的代码,它返回总和的值。所以,当我将具有该返回值的函数输出保存到另一个变量时。所以,print 的输出被执行,输出也被存储。所以,无论函数返回什么,在这种情况下,它返回总和,该返回值存储在 output 变量中。现在,在以前的情况下,函数没有 return 语句。所以,函数没有返回任何东西。所以,这里没有保存任何东西。现在,这里返回了总和的输出值。所以,返回的值被保存,这就是我们能够检索到的。到目前为止,我们创建了两个不需要任何输入参数即可执行的函数。现在,我正在重写该函数,它将接受用户姓名作为输入参数,并使用该姓名构建此字符串,并且该字符串将由函数返回。所以,让我用我的名字试试。它说欢迎来到 Python 课程 prashant。所以,这个字符串被连接到原始字符串,最后你可以看到有一个空格。所以,这个名字本质上是一个字符串,这个加号基本上是在进行字符串连接。好的,连接后的字符串最终由函数返回。你实际上可以保存输出并进行验证。好的,所以,output = welcome,让我们这次说 Harry。让我保存。而且,输出在这里检索。完美。现在,你还可以指定输入参数的默认值。好的。所以,在这种情况下,name 有一个默认值。好的。所以,你可以看到,如果你在调用函数时提供了输入参数的名称,它将覆盖默认值。默认值的优点是,如果你在调用函数时忘记提供任何输入参数,则将使用默认值。好的。所以,让我们看看。所以,它仍然说否则,如果不提供默认值,这个空的函数调用将返回一个错误。所以我只是改变了这个函数,以便删除了默认值。现在你可以看到这个工作了,因为它无论如何都接受一些输入参数,这些参数映射到 name。但是,这里会抛出一个错误。缺少一个必需的位置参数。好的。而那个必需的位置参数是 name。由于 name 的值丢失了,这就是你得到的错误。好的。所以,为了应对这种情况,你可以提供一些默认值,如果调用函数时没有提供特定输入参数的必需值,就可以使用这些默认值。好的。如果你对函数进行了更改,请不要忘记再次执行该代码块,以便更新后的函数进入内存,然后你再调用它。所以,刚才我们看到了位置参数的概念。现在,有两种类型的输入参数。一种是位置参数,另一种是关键字参数。好的。所以,什么是位置参数?让我们更详细地看看。所以,这是一个我正在创建的函数,数学函数,它接受两个数字,一个较小的数字和一个较大的数字。所以,它返回什么?它返回较大数字和较小数之间的差值。非常简单的函数。所以,4 和 16,以及 16 和 4。如果你能清楚地看到,你提供值的顺序非常重要。好的。因为 4 和 16 之间的差值基本上是,如果你看到这个 4 被映射到较小的数字,而这里的 16 被映射到较大的数字。但是在这种情况下发生了什么?16 被映射到较小的数字,而 4 被映射到较大的数字。所以,遵循的顺序与函数定义中声明的顺序相同。好的,这正是位置参数的概念。所以,输入参数的位置很重要。好的,你在哪个位置给出数字,这里就遵循相同的顺序。好的。所以,现在让我们看看关键字参数。所以,如果你定义了关键字,那么我们可以按任何顺序定义输入参数。所以,现在你说 larger number 取值为 16,smaller number 取值为 4。所以,这里我将 larger number 放在 smaller number 之前。你也可以将 smaller number 放在 larger number 之前。只要你根据输入参数的确切名称赋值即可。现在,这不能是任何变量名。它必须是函数期望的相同的变量名。好的。所以,如果你在这里定义为 a 和 b,那么你也必须在这里提供为 a 和 b。好的。所以,你必须记住这一点。这样做的优点是,你可以看到,由于 larger number 被映射到 16,无论是在开头还是在结尾都不重要,larger number 和 smaller number 之间的差值仍然是 12。好的。所以,这次即使传递参数的顺序不同,也返回了一致的输出。好的。现在,问题就开始了,当你试图混合搭配时。这里有一个关键字参数,这里是一个位置参数。这将抛出一个错误,说位置参数跟随关键字参数。所以,如果你在调用时传递输入,如果你在不将其映射到确切的输入参数名的情况下为函数提供输入,那么它就成为一个位置参数。所有位置参数都必须在任何关键字参数之前定义。所以,这里,由于你通过定义要映射到的变量名来传递 4 的值,这成为一个关键字参数。而这里没有指定 16 要映射到哪个变量。所以,这实际上是一个位置参数。简单。所以,这必须以相反的方式完成。好的。所以,这里 4 是位置参数,16 是关键字参数。然后,这正是这个语句所说的。所有位置参数都必须被定义。好的,在关键字参数之前,正确?所以,这也会起作用。现在,让我们看看函数内外的变量作用域。所以,变量的作用域是什么意思?所以,这是程序中我们可以访问特定变量的部分。好的。所以,你现在在笔记本中创建的所有这些变量都可以从这里的全局命名空间访问。所以,你可以看到全局命名空间拥有内存中的所有函数。这些是所有函数现在存在的内存位置。好的,以及你创建的所有变量也存在于此。你的 name、output 1、2、3 和 welcome。所以,所有这些都是你在本特定笔记本中创建的函数和变量。所以,这是这个笔记本的范围,全局范围。好的。所以,这是你所有变量存储的地方。所以,全局变量和局部变量。所以,每个函数都有自己的局部范围或命名空间,它在那里存储变量,这些变量被称为局部变量。所以,首先,让我们看看我有一个名为 name 的变量,它定义在函数之外。所以,默认情况下,在函数之外定义的任何变量都在全局命名空间中。好的,它们在全局命名空间中。全局命名空间意味着这是一个全局命名空间,因为所有这些变量都在函数之外定义的。所以,它将进入全局命名空间。所有存在于全局命名空间中的函数。你可以看到,有我们创建的函数。所以,这些存在于全局命名空间中的函数将能够访问所有存在于其中的变量。所有这些函数都将能够访问全局命名空间中的所有这些变量。默认情况下。所以,这里这个 name 可以被这个函数访问,这就是为什么这个函数能够返回那个 name,或者你也可以做一些计算。所以,让我将那个 name 乘以五,或者乘以二,看看会发生什么。所以,让我调用那个函数。你看到它被复制了三次。字符串乘以整数意味着基本上将该字符串复制三次。好的。所以,这是第一次,第二次,然后是第三次。所以,字符串被复制了三次。我能够访问在函数外部创建的变量。而且,如果你看到那个变量的值没有改变。所以,在函数内部进行了计算,我的意思是进行了操作,但在函数外部,它仍然保持不变。所以,我正在打印函数外部 name 的值,它仍然是相同的。所以,假设你想在函数内部更改这个变量的值。所以,这个 name 将存在于全局命名空间中。所以,这本质上是一个全局变量,我创建了它的另一个副本在函数内部。就在不久前,我提到每个函数都会创建自己的命名空间。所以,这是函数内的命名空间。我正在创建这个变量。所以,这个变量成为该函数的局部变量。所以,本质上,这个 name 是该函数的局部变量。好的。所以,这个 name 进入局部变量命名空间。好的。这个 name 在全局变量命名空间中。好的。所以,函数可以覆盖。所以,这个函数覆盖了 name。好的。并且,它创建了一个同名的局部变量。所以,它将不再可访问。函数将只访问这个并返回它。好的,完美。所以,如果你看到 name 的值已经与函数外部的变量相同。好的。所以,函数可以拥有只读访问权限,就像在本例中一样,你可以看到它具有只读访问权限,但假设你想更改或更新全局变量的值。基本上,你也想对全局变量拥有读写访问权限。为此,你需要将你想要提供给该函数进行读写访问的变量定义在函数空间或局部变量空间内,作为全局变量。所以,这个 global 关键字使该函数能够对这个全局变量进行读写访问。现在,所以这个 name 将被这个函数修改。所以我在这里修改值。当我调用那个函数时,你可以看到 name 的值已经改变了。所以,这是在函数外部定义的。而且,在函数内部,值被改变了。而且,我现在正在访问函数外部变量的值。它仍然给我函数内部定义的值。所以,这就是你可以创建一个全局变量,甚至多个函数都可以共享它。所以,每个函数仍然可以以读写访问模式共享相同的值,前提是你为所有你想以读模式共享的函数提供全局关键字。欢迎来到 Python 中的模块和包课程。模块和包是非常有用的工具,它们帮助我们保持代码的组织性、可重用性和易于管理。今天,我们将探讨它们是什么,如何创建它们,以及为什么它们对任何程序员都很重要,特别是当你的项目不断发展时。让我们开始吧。让我们从理解 Python 中的模块开始。简单来说,模块是一个包含 Python 代码的文件,通常是函数和类定义,我们可以在不同程序中重用它。它帮助我们以逻辑方式组织相关代码。Python 模块的文件扩展名是 py。要创建模块,你只需要创建一个新的 Python 文件。例如,my_module.py。在此文件中编写你的 Python 代码,然后保存它。它就可以使用了。模块就像橱柜里的抽屉。它们有助于将相关项目分组在一起,使你在需要时更容易找到和重用它们。想象一下,Redford 学校被委托开发一个学校管理系统。该系统需要处理学生管理、教师管理、费用计算和评分。最初,他们可能会将所有内容放入一个文件中。我们称之为 school_management.py。但是随着功能的数量增长,这个单一文件变得庞大且难以管理。找到特定代码片段变得困难。在不破坏其他东西的情况下进行更改是一场噩梦。这就是模块的用武之地。现在,Redford 学校决定将学校管理系统分解为更小的逻辑模块,而不是一个大文件。student_management.py 用于学生相关函数。teacher_management.py 用于教师相关函数,fee_calculation.py 用于处理所有费用相关任务,grading_system.py 用于管理成绩。这样,代码就是模块化的,更容易管理,而且出错的可能性大大降低。如果你需要更改评分系统,你可以只打开 grading_system.py,而无需担心学生或教师管理代码。现在,让我们看看如何使用这些模块。学生、教师、费用和评分的所有不同模块都可以拉到一个主脚本 main.py 中。该脚本协调所有模块,使其成为应用程序的控制中心。现在,想象一下,如果学校注意到管理系统不断增长,他们可以通过将功能分解为更多模块来进一步模块化。这种灵活性有助于在项目发展过程中保持代码的组织性。当模块不足以管理不断增长的代码库时,我们就会转向包。想象一下,Redford 学校决定进一步扩展其系统。他们创建了一个学生管理包,其中包含注册、出勤和个人资料管理模块。他们还有教师管理、费用管理等包。每个包代表系统的逻辑区域,每个包内的模块处理与该区域相关的特定任务。这非常类似于百货商店的组织方式。你有服装、电子产品和杂货的不同区域。在 Python 中,包本质上是一个包含多个模块文件和一个下划线_init_.py 文件的文件夹,该文件告诉 Python 此文件夹应被视为一个包。包甚至可以包含子包,它们只是文件夹内的文件夹,每个都有自己的 init.py 文件。例如,我们的学校管理包可以包含学生管理、教师管理和费用管理等子包。这使我们能够以有组织和逻辑的方式扩展我们的代码库,从而轻松找到和维护我们系统的不同部分。那么,我们如何在主脚本中使用包呢?这很简单。你引用包名、子包名,然后是你想要使用的模块或函数。例如,如果你想使用学生管理包中的 enrollment 函数,你可能会写类似 from school_management.student_management.enrollment import enroll_student 的内容。感谢你加入我关于理解 Python 中的模型和包的旅程。我希望你现在能体会到这些工具对于组织和管理你的代码是多么重要。它们有助于保持你的项目干净、高效和可扩展,让你的程序员生活更加轻松。继续练习。尝试创建你自己的模块和包,我将在下一节中见到你。在本视频中,我们将学习 Python 的最佳编码实践。所以,Python 的最佳编码实践对于拥有良好的代码可读性、可维护性和代码的最佳效率是必需的。所以,我们将遵循一些指南,特别是 PEP 8 和 PEP 257 风格指南,它们将帮助我们编写更清晰、更 Pythonic、对 AI 开发友好的代码。让我们开始吧。所以,在这个笔记本中,我们将涵盖这四个主题。呃,如何在 Python 中编写干净的代码,有效使用注释,然后如何为 AI 开发编写 Pythonic 代码。我们将举大约 9 到 10 个例子,然后我们将举一些 PEP 8 和 PEP 257 风格指南的例子。所以,关于第一个,如何在 Python 中编写干净的代码。我给了一个简单的例子,我将演示一个糟糕的代码,然后是一个好的代码。好的,让我们看第一个例子。所以,在这个第一个例子中,我演示了如何编写有意义的变量名和函数名。好的,所以在糟糕的代码中,你能看到函数名非常短,而变量名只是 a 和 b。所以,我们应该避免单字母变量名,函数名也应该是自解释的。好的。所以,虽然这是一个可工作的代码,你可以检查一下,但这个代码的更好版本是编写一个合适的函数名,它是自解释的、说明性的,并且你使用的任何输入或变量名也必须稍微更具描述性、语义性。好的,你提供两个数字作为输入。所以,让输入被称为 first number 和 second number,然后你可以对这两个数字进行任何计算并返回它们。所以,这里的函数比 cal 函数更具描述性,参数名也更具描述性。在第二个例子中,我们演示了糟糕的代码会包含硬编码的常量值,这会使代码难以重用或调试。好的。所以,例如,这里你想返回折扣价。所以,函数名是好的,calculate_discount,它接受价格作为输入,以及该价格的 10% 将是总折扣。但问题在于,10% 的折扣是硬编码的。所以,之后,如果你想改变折扣率,你可能需要深入研究该函数在哪里,然后回到这个变量。所以,不是个好主意。呃,我们可以提供那个折扣率作为更像一个全局变量,然后使用它,因为函数默认可以访问所有全局变量。所以,你正在访问那个折扣率,它在这个笔记本中被设置为一个常量,让我们说,然后使用折扣率来计算总折扣。所以,这更具可读性,并且更容易更改,因为现在你只需要更改此变量中的值。现在,我将演示如何编写适当的注释和注释的代码块。所以,甚至在去那之前,有一个糟糕的代码示例,它试图注释每一行代码,即使代码可能非常明显。这也不是个好主意。所以,例如,如果你看到在这种情况下 x = 10,y = 20,z = x + y。所以,这些是注释,将 10 分配给 x,将 20 分配给 y,然后将 x 和 y 相加。所以,非常清楚我将 x 分配为 10,y 分配为 20。所以,实际上不需要这些注释,而且这个操作也相当自解释,对吧?所以,在好的代码中,你不需要实际。所以,这又是一个常量 birth_year,current_year,我试图得到 current_year 和 birth_year 之间的差值来计算年龄。所以,这个计算可能不是非常直观。所以,这就是为什么我在这里提供了一个注释。但我跳过了在这些两行中提供注释,因为无论如何,它都相当自解释,对吧?代码很明显。所以,理想情况下,当你试图解释为什么要做某事时,应该在你的代码中添加注释。另一个例子,你在这里写了一个函数,一个好的代码会让你大致了解那个函数在做什么。所以,这被称为 docstring。你可以看到三个双引号开始,三个双引号结束。所以,这个块中的任何内容都被称为 docstring。简而言之,文档字符串,即 docstring。所以,理想情况下,在 docstring 中,你应该能够提供函数的作用,它接受什么样的输入,它做什么计算,以及它返回什么样的输出。所以,一切都应该以 docstring 标准进行记录。所以,我们将在笔记本的后面部分看到关于 docstring 的更多细节。所以,目前我有一个函数,它至少让我们大致了解那个函数的作用。好的。所以,让我运行这段代码,向你展示拥有这个文档字符串的好处。所以我只是使用 calculate_area,呃,如果你看到,我现在正在按键盘上的 shift tab,或者 shift tab tab,shift tab 将为你提供关于该函数的快速 docstring。所以,没有这个,没有这个 docstring,没有,很难弄清楚那个函数在做什么。好的。所以,让我把它去掉,呃,再给你看那个函数。所以,现在我又在做 shift tab tab。如果你看到 docstring,没有提供 docstring,而这正是我试图传达的。所以,提供 docstring 是个好主意,这样我们就能知道那个函数的作用。现在,让我们看一些关于 AI 代码的 Pythonic 指南的更多例子。所以,在第一个例子中,我们看到我们应该更频繁地使用列表推导式,而不是使用朴素的简单循环进行数据转换。所以,让我举个例子。呃,我创建了一个空列表,好的,我想将数字的平方存储在那个列表中。所以,我该怎么做?所以我在这里做的是迭代一个从 0 到 9 的 10 个数字的范围,并且对于每个数字,我将它的平方存储或附加到那个空列表中。所以,一个接一个地,通过这些迭代,数字将被平方并附加到那个空列表中。好的。所以,最后我将得到一个包含 0 到 9 的 10 个数字的平方的列表。所以,我们可以使用列表推导式将这三行代码压缩成一行。所以,这是我的列表推导式。所以,我在这里做的是创建一个列表。你可以看到方括号表示创建列表,并像往常一样使用 for 循环。并且对于 i in range(10),将 i 的平方值保存在那个列表中。所以,你在同一行代码中创建列表并迭代那个 10 个数字的范围。所以,这就是我们称之为 Pythonic 代码的东西。所以,这些 Pythonic 代码比这些朴素的 for 循环代码更受青睐。另一个例子是,假设你想同时访问一个可迭代对象的索引和值。这里我的可迭代对象是一个包含三个字母的列表,A、B 和 C。好的,这是一个列表,我将迭代这个列表。所以,我想访问索引,即 0、1 和 2。
以及值。所以这是一个 for 循环。我正在遍历该数据,对于 item in data。打印索引,item。我将索引初始化为零,然后在我访问该索引后,在 for 循环中手动递增该索引。所以这是一种访问索引并递增它的非常好的方法。更好的方法是使用 enumerate 函数。所以对于 item,对于 index,item in en in enumerate data。那么 enumerate 函数做什么呢?Enumerate 函数将创建一个索引,此外它还将为您提供一种直接访问值的方法。所以它生成两样东西。它也是一个生成器函数,就像 range 一样,但 range 函数只生成数字。Enumerate 函数生成两样东西。一个是索引,它是数字,然后值是从数据本身获取的。所以当你运行这个时,让我运行一下。所以输出是相同的,但这更具 Pythonic 风格。好的,这更容易理解。所以 enumerate 函数实际上返回一个元组。元组的第一个元素是索引。元组的第二个元素是项。您可以直接访问项以及该项的索引。现在,关于 pep 8 和 pep 257 风格指南的一些更多示例。所以我们先从 pep 8 开始。所以 Pepe 谈论了如何根据变量、函数、类的命名法来编写更好的 Python 代码。您应该使用多少个空格?您应该在哪里使用这些空格?您应该使用多少个空格进行缩进?缩进应该在哪里提供?嵌套或深度嵌套缩进是如何完成的等等。好的。PEP 是 Python 增强提案。所以您可以通过遵循此链接详细查看 PEP 8 指南,并且这是由 Gaidoan Rasum 撰写的。他是 Python 语言的创建者。好的。所以您可以从这个文档页面获取有关 pepaid 指南的详细信息。所以在这里我将讨论最重要的风格指南。首先是关于变量命名约定。所以再次我已经在重复了,但再次我在这里重复。所以不要提供只是单个字母的变量名。它们不清楚,并且很难弄清楚它们代表什么,它们保存什么类型的数据等等。好的。编写更具描述性和语义性的变量名。这就是我们所说的 snake case。基本上使用下划线分隔变量名中的多个单词。所以如果宽度是 10,高度是 20,矩形的面积将是宽度乘以高度,而不是简单地写 xy 和 z 等于 x 乘以 y。所以这更具描述性,更有意义。所以稍后当您回到您的代码时,通过查看这段代码,您会立即知道您在做什么,您在进行什么计算,您将在哪里使用该计算函数命名约定。所以所有函数名都必须始终以小写字母开头。所以您应该再次使用 snake case,而不是使用 camel case。所以 camel case 以大写字母开头,中间有更多大写字母。这就是我们所说的 camel case。所以 camel case 保留用于在 Python 中命名类,而不是函数。对于函数,我们应该再次使用 snake case。所以如果你想计算面积,这也不是一个很好的函数名。为什么?因为这又太短了,无法理解发生了什么计算。对吧?如果你想计算面积,写下 calculate area,这可以是简单的 calculator,income calculator。它可以是 MI calculator。它可以是任何其他随机 calculator。对吧?所以这是编写函数名的一种更好的方式。或者如果你正在计算一个商品的总价,好的,写下 calculate total price,函数名不能包含空格。所以用下划线替换空格。同样,对于命名常量,尝试使用大写字母。正如您在我们的第一个示例中可能已经注意到的,我们使用了大写的 discount rate。所以如果这些在您的笔记本中定义为常量,请尝试为这些常量使用大写字母。所以类名应该使用 camel case 而不是 snake case 或小写字母。所以这是糟糕的命名法。所以 P 应该在这里大写,我们还应该避免使用下划线。好的。所以这是一个 camel case。P 是大写的。D 也是大写的。所以避免使用下划线。虽然这没有错,Python 在这种情况下不会抛出错误,但它违反了 PEP 8 风格指南。下一个示例,我们应该在运算符周围添加一个空格以提高可读性。如果你看到这里,使用了三个运算符。好的,一个是等号。另一个是加号,然后最后一个是乘号。所以这三个运算符,但没有空格。所以理想情况下,我们应该使用足够的空格,足够的意思就是只有一个,不要太多。所以您应该至少在两侧用一个空格分隔运算符和操作数。这里的另一个例子是关于缩进和行长的。所以在这个例子中,如果我们看到,我们应该使用一致的缩进。所以所有缩进都应该是四个空格,总行长应小于 79 个字符。所以如果您的行倾向于包括注释,倾向于超过 79 个字符,最好换行,即使这意味着换行注释,这是完全可以接受的。所以功能上两者都是相同的。功能上两者都是相同的,但请确保您为第一个缩进使用四个空格,然后为下一个缩进使用八个空格,依此类推。它不能是三个空格然后四个空格,您不能随意增加或减少空格的数量。所以如果你看到,如果你尝试使用不一致的空格数运行此代码,这甚至可能导致错误。所以您还应该在定义函数和类时使用空行。至少两个空行。这里我定义了一个函数和一个类,但类定义和函数定义之间没有空格。所以这里我有两个换行符。好的。在我开始定义我的,好的,再次这里,类名,它仍然是一个机器学习模型,它是我的类名,它应该再次以 camel case 而不是 snake case,这是我们在这里再次犯的命名错误,而且,如果你看到函数定义,它是 camel case,而不是它应该是 snake case,所以你不能互换它们。另一个非常常见的错误是人们试图过度使用等号运算符。这是为了检查某事物的相等性,或者一个变量是否等于某事物。所以,假设您的变量值是 10,并且您想检查该变量是否为 None。好的。所以最好使用 if variable is none。而不是使用这个。而不是检查变量的值是否为 None。检查变量本身是否为 None。所以这是处理这种情况的一种更好的方法。如果你想检查它是否与 None 进行比较。如果你想检查它是否与某个其他数字进行比较,那么这是可以的。如果你想与例如 100 进行检查,那么这段代码是完全可以的。但如果你正在与 None 进行检查,那么最好的方法是这样做。最后,我们应该避免导入任何未使用的模块。所以,例如在这段代码中,我想找出给定数字的平方根,我为此定义了一个函数。所以在这里您可以看到我导入了 math 模块、os 模块和 random 模块,而我没有使用它们。所以这不是一个好的编写代码的方式,只是导入占用内存的模块。所以更好的方法是,如果您可以通过自己的代码或一些自定义函数来重现功能,那是最好的。在这种情况下,只有这个函数保留在内存中,而不是我们无论如何都不使用的所有冗余模块。所以在这种情况下,如果你愿意,你也可以导入 math 模块,并且实际上 math 模块正在被使用。所以这也是可以接受的。在最后的演示中,我们将演示 PEP 257 风格指南。所以,PEP 257 讨论了 Python 编码的文档字符串标准。所以,通常文档字符串应该描述函数的功能、输入和输出参数以及它返回的内容。所以您在函数定义下方看到的所有内容,都包含在这三个双引号中,这简称为 docstring 或 documentation string。如果您定义了一个没有文档字符串的函数,它仍然可以使用。您可以看到我能够创建一个函数,该函数通过将圆柱体的半径和高度作为输入来计算圆柱体的体积,并且我能够通过为半径和高度提供一些值来调用该函数。然而,当我执行 shift tab tab 来检查函数文档时,您可以看到这里没有提到文档字符串,因为我们删除了该文档字符串。现在,让我将其放回,重新初始化函数,然后使用该函数。所以,功能上没有任何变化。然而,如果你现在看到,我将执行 shift tab tab,将光标放在函数内。所以会出现这个气球弹出窗口,它谈论文档字符串。所以这给了我一个清晰的指示,这个函数做什么,在这种情况下,使用半径和高度作为输入计算圆柱体的体积。输入参数及其格式是什么,以及函数返回什么,在这种情况下,它是圆柱体的体积,以浮点格式返回。对吧?所以这是定义函数的适当方式,并且我们进一步使用它们。所以,这就是本视频的全部内容。谢谢。大家好,欢迎来到 NumPy 课程。NumPy 是 Python 数据科学生态系统的基石,它提供了 ndarray 对象用于高效的数组操作以及大量的数值函数。在本视频中,我们将探讨它是如何工作的,为什么它对数据科学至关重要,以及其关键特性,如通用函数、随机抽样和线性代数例程。NumPy 代表数值 Python,它围绕着 ND 数组,即 N 维数组对象数据结构构建。所以与纯 Python 列表不同,ND 数组对象效率更高,并支持矢量化操作,这意味着您可以对整个数组应用操作而无需编写任何循环。这使得您的代码运行更快,并且更容易阅读和维护。此外,由于 NumPy 非常基础,其他流行的数据科学库,如用于表格数据的 pandas,或用于科学计算的 sci,甚至用于机器学习的 scikit-learn,它们在底层都大量使用 NumPy 对象。NumPy 的通用函数或 ufuncs 对数组执行逐元素操作。例如,对于基本算术运算,如加法、减法、乘法和除法。这非常直接。我们调用 np.add 函数或直接写 a + b。我们还有指数函数和对数函数,它们逐元素进行操作。现在这种程度的矢量化速度很快,并且使我们的代码简洁易读。如果您处理任何类型的科学或工程数据,三角函数很可能会出现。NumPy 提供了一整套三角函数,如 s、cosine、tangent 等,以及它们的逆函数,所有这些函数都逐元素工作。双曲函数也是如此。所以,无论您是在建模波浪、处理信号处理,还是分析周期性数据,NumPy 都能满足您的需求。有时您需要清理数据,通过四舍五入值。也许您正在处理货币,或者您只是想要更少的十进制位数,这时这些四舍五入函数就派上用场了。所以您可以使用 np.round 函数,它会将您的数字四舍五入到最近的十进制位。np.floor 函数会将数字向下取整到整数。np.ceil 函数会将数字向上取整到整数,等等。所以您还有 np.sign,即符号函数,它返回一个数字是负数还是正数的指示。如果数字是负数,它将返回 -1。如果数字是正数,它将返回 +1。如果数字是零,它将返回零。现在这些比较和逻辑函数使得生成布尔掩码非常容易。例如,您有一个函数 nples。根据每个元素是否满足某个条件,例如小于某个数字,它会返回一个真或假值的数组。所以您可以使用这些布尔函数和数组来过滤数据并应用条件逻辑。有一些位运算变体,它们非常相似,但作用于位级别,这在某些底层和专用任务中非常有用。没有数据科学项目会缺少计算汇总统计。所以 NumPy 内置的统计函数非常直接。您有 np.std 函数,它计算 NumPy 数组的标准差。您还可以为这些函数指定一个轴来计算这些统计数据,无论您是想逐行还是逐列计算,这使得它对于多维数据非常灵活。继续讨论 NumPy 的核心功能。在这里,您将学习使用诸如 np.array、np.zeros、ones 等基本函数创建数组。在处理不同形状时,您可以使用 np.shape 和 reshape 函数来更改向量和矩阵的形状。您可以使用 ravel 函数来展平您的数组和矩阵。最后,使用 transpose 函数来翻转轴,将行变成列,等等。有一个 dtype 参数,可用于获取 NumPy 数组中存在的元素的类型。而您有 astype 函数,用于更改 NumPy 数组中元素的类型。这也被称为类型转换。掌握这些基础知识是充分利用 NumPy 的关键。广播是 NumPy 最强大的功能之一。它允许您在不同形状的数组之间执行算术运算,通过自动拉伸它们沿着任何长度为 1 的维度或没有维度。例如,如果您将一个标量,比如 5,加到一个二维数组上,NumPy 会有效地将该标量复制到整个数组的形状中,以使该操作成功。让我们考虑另一个快速示例。这里有一个形状为 3 的数组 A,以及一个形状为 3, 1 的数组 B。本质上 A 是一维的,而 B 是二维的,有三行一列。所以这些数字 10、20、30 存在于一列中。它本质上是一个列向量。而 A 是一个一维对象。所以现在如果您想在它们之间进行操作。让我们考虑 a + b。好的。所以您正在将一个一维 NumPy 数组与一个二维 NumPy 数组相加。在这种情况下,NumPy 会根据需要拉伸 A 或 B。所以形状变得兼容,以便操作成功。所以最终结果是一个 3x3 的矩阵。所以当正确使用时,广播可以节省大量代码,并使您的计算非常高效。因此,理解从最后一个维度开始匹配形状的规则也很重要,以避免不匹配和错误。现在让我们谈谈线性代数。许多数据科学或机器学习算法涉及向量和矩阵。考虑大型数据集或变换或求解方程组。现在使用 NumPy 的 lin alg 或线性代数子模块,您可以使用 np.dot 函数或一个非常方便的运算符,即 @ 符号来相乘矩阵。您还可以使用 np.linalg.solve 函数来求解线性方程组 ax = b,而不是自己编写求解器。如果您需要找到矩阵的逆或行列式,您必须选择线性代数模块中现成的函数。对于更高级的用例,您可以通过 np.linalg 模块获得特征值和特征向量。您还可以使用 np.linalg.svd 进行奇异值分解,这在降维的主成分分析等方法中非常关键。您还可以使用 linalg.norm 函数找到向量和矩阵范数。虽然 NumPy 没有单独的统计子模块,但它在其主命名空间中包含了一些统计函数。例如,np.mean 可以计算平均值。您可以指定一个轴来执行此操作,以便在二维数组中逐行或逐列计算。类似地,您有 np.median 函数,np.quantile 函数,它们可以帮助您理解数据分布等等。而 np.std 和 np.var 这些函数计算数据的标准差和方差,这有助于您理解数据的分布。所以这使得 NumPy 在进行探索性数据分析之前,在您转向更高级的工具之前,是一个很好的起点。如果您需要理解变量之间的关系,例如计算相关系数,您有 np.corrcoef 函数,您还可以使用 np.cov 函数计算这些矩阵之间的协方差。您有 np.histogram 函数,它有助于将连续数据分桶到箱中,以进行基本频率分布。现在这些函数虽然简单,但在深入研究 pandas 或 seaborn 等专用库进行可视化之前,对于快速了解数据行为非常强大。最后是 numpy.random 模块,我们在这里生成用于模拟、随机算法或测试数据的随机数。推荐的方法是使用 np.random.default_rng 函数创建一个随机数生成器。您可以提供一个种子,无论默认值是多少,通常是 42,这使得您的结果非常可重现,这在许多科学和数据科学环境中至关重要。您还可以从各种分布中进行采样,如正态分布、均匀分布或二项分布等等。此外,您还有一个名为 shuffle 和 permutation 的函数,当您需要打乱数据时,例如随机化数据集中的行顺序,甚至创建排列时,它们都很有用。无论您是执行蒙特卡洛模拟,还是只需要快速采样数据进行测试,numpy.random 模块都是您的首选函数。这结束了对 NumPy 关键功能的探索,从数组创建到广播,再到通用函数、线性代数甚至随机抽样。理解这些概念将帮助您编写更快、更简洁的代码,并为您在 Python 数据科学领域打下坚实的基础。大家好,欢迎回来。在本视频中,我将演示如何使用 NumPy 函数。我将向您展示如何创建和操作 NumPy 数组和矩阵。我们还将执行矢量化算术运算,使用一些统计函数,并且我们将看到 NumPy 中的广播是如何工作的。我们还将从线性代数和随机模块中选取一些函数。所以,让我们开始吧。所以首先我们需要导入 NumPy。NumPy 通常预装在任何 Anaconda 安装中,无论您是在 Jupyter Notebook 中运行还是在 Colab 中运行,NumPy 都预装了,所以您不必真正担心安装 NumPy。所以让我们将 NumPy 导入为别名 np,并且为了可重现性,尤其是在处理随机数时,我使用默认种子 42。我在此笔记本中运行的 NumPy 版本是 1.26.4。好的,让我们看一些数组创建函数。所以,我们将主要使用 np.array 函数来创建数组。除此之外,我们还可以使用 zeros、ones、arange 和 linspace 函数。让我们逐一查看它们。所以,这里我有一个数字列表 1 2 3 4 5。这是一个普通的 Python 列表。我将把这个普通的 Python 列表转换为 NumPy 数组。好的,通过使用 np.array 函数。所以这是一种将 Python 列表转换为 NumPy 数组对象类型的类型转换。我们可以通过使用 type 函数来验证这一点。您可以看到数据类型是 numpy.ndarray。所以它是一个 NumPy N 维数组对象。它不再是列表了。对吧?所以现在让我创建另一个二维零数组。好的。所以我将使用 np.zeros 函数,它将有两行三列,所有都填充为零。所以这是两行,一和二,以及三列。类似地,我可以使用 np.ones 函数创建另一个二维对象。所以再次,这将是两行三列。好的,所有都填充为一。您还可以使用函数检查维度。所以让我们看看 array_ones.shape。所以您可以看到它有两行三列。所以还有一个函数可以检查维度。那就是 ndim。您可以看到显示的维度是二。所以您可以检查任何 NumPy 数组的 ndim 参数来查找该 NumPy 数组的维度。好的。所以现在我想使用另一个函数 arange 创建一个数组。这个函数的作用是它接受一个起始数字,在本例中是 5,然后有一个结束数字,是 15,以及步长 2。所以它将开始为您提供数字,或者创建一个从数字 5 开始的数组,并且它将在结束数字之前停止。所以 15 将不会包含在该数组中。好的。所以 5 6 7 8 9 10 11 12 13 14 将是最后一个数字。技术上。但是然后您说给我一个步长为 2。所以这意味着它将跳过每隔一个数字。让我们看看在我删除那个 2 之后会得到什么。所以这是从 5 到 14 的确切预期。但是如果我把那个 2 拿回来,它将跳过每隔一个数字。所以我会得到 5 然后我会得到 7。我会得到 9。跳过了交替的数字。好的。所以我会得到 5 7 9 11 和 13。这将是最后一个数字。完美。好的。所以,步长您可以设置为 2 3 4 无论那个数字有多少个数字将被跳过。好的。另一方面,linspace 将始终确保起始数字和结束数字始终包含在 NumPy 数组中。所以这次我将创建一个 NumPy 数组,它同时包含 0 和 1。以及我想要在该数组中有多少个数字,由这个 5 指定。好的。而不是指定数字之间的间隔,您指定您想要在该数组中有多少个数字,包括 0 和 1。好的。所以 Python 将回溯计算间隔,并且您正在谈论这些数字之间的线性间隔。好的。所以让我们看看。所以您可以看到 0 和 1 都包含在内,并且 Python 回溯计算了另外三个数字,使得这五个数字之间的间隔相等。这就是该数组中的线性间隔数字。让我们看看索引和切片的概念。所以通过使用索引和切片,您可以访问 NumPy 数组中的元素。如果您愿意,您甚至可以修改其中一些元素。好的。所以让我创建一个简单的 NumPy 数组 10 20 30 40 50。这是一个简单的一维数组,数组元素通过方括号访问。所以这是我的索引括号。如果您看到这是我的索引括号,并且我想要访问的元素索引是 2。现在我在这里写了 Python 是零索引的,这意味着数组中的第一个元素索引为零。这将是索引一。这将是索引二,这将是索引三,这将是索引四。所以最后一个索引将始终是数组总长度减一。好的。所以在这个例子中,我将得到 30,因为这基本上是第二个索引。所以 0 1 和 2。这是 0 1 和 2。好的。如果您愿意,您也可以在索引时指定起始和停止索引,以及可选的步长。所以在这个例子中,我给出了起始索引为 1,停止索引为 4,并且再次停止索引将永远不会包含在切片中。它将始终在停止索引之前停止。所以在这里我将得到索引为 1、索引为 2、索引为 3 的数字。就是这样。好的。所以我会得到三个数字。是的。所以那是 20 30 和 40。所以 20 是我的索引 1。30 是索引 2,40 是索引 3。所以在这个例子中,冒号,这个冒号意味着获取整个数组,并给我每隔一个元素。所以由于您没有提供起始索引,它将从零开始。由于您没有提供停止索引,它应该放在这两个冒号之间。所以由于您没有提供那个数字,它将一直到数组的末尾。所以从开始到结束基本上选择整个数组。但是现在您想选择步长为 2 的数字。所以每隔一个元素将被选中。好的。现在让我们看看索引和切片如何处理多维数组和矩阵。所以让我先创建一个二维矩阵。所以这里我有了数字 1 2 9,以 3x3 的格式排列。所以三行三列。这些是行 1 2 3 4 5 6 7 8 9。这是三行,这是列 1 4 7、2 5 8 和 3 6 9。现在我想提取索引为 1 2 的元素。所以这是我的行索引,这是列索引。现在行索引是什么?所以这是第一行,索引为零。第二行索引为一,第三行索引为二。好的。所以我要求它给我第一个索引的行,这意味着第二行。所以这一行索引为一。所以第二行和列索引是二。第一列索引为零。第二列索引为一。第三列索引为二。所以本质上您是在说给我第二行第三列的元素。所以在这里您可以看到它相交于六。完美。您还可以提供行索引和列索引的范围。好的。所以 0:2 意味着它将取行 0 和 1,2 将被排除。所以行索引 0, 1 和列索引 1 和 2,因为再次 3 将被排除。所以行索引 0, 1 意味着前两行,列索引 1, 2 将是最后两列。所以前两行和最后两列本质上将给我 2 3 5 6。让我们看看。所以这正是我们所说的二维切片。好的。您还可以提供手工选择的行和列索引。所以在这个例子中,假设我想从第一行和最后一行选择元素。在这种情况下,最后一行索引为二。所以这是您提供的索引,冒号意味着获取所有列。所以在这里您提供行索引 0, 2,冒号意味着在这里列边,这个冒号意味着获取所有列。所以给我行索引 0, 2 和所有列。所以让我们看看我得到了什么,因为我要求了所有列。所以您可以看到我能够获得所有三列和前两行。好的。所以如果我把这个 2, 0 呢?所以好的一点是,我将得到最后一行,然后是第一行。所以只是看,第一行现在实际上变成了最后一行。好的。所以您可以看到这两行实际上翻转了,因为索引翻转了。所以您可以根据您想要的特定索引检索行和列。这就是我所说的花式索引。好的。让我们看看布尔索引是如何工作的。这里您将提供一个条件。所以在这里我说的意思是给我这个二维数组中所有大于 4 的元素。所以这将创建一个布尔掩码。布尔掩码只不过是一个与此形状相同的数组,它只有真和假。所以那些满足此条件的职位是真,而所有元素小于 4 的职位是假。好的。当此条件不满足时,本质上。所以让我先打印布尔掩码。您可以看到在这些位置我有一个大于 4 的数字。这就是掩码的确切含义。当您传递该掩码时,该掩码成为布尔索引。本质上它是一个布尔索引。当您将该布尔索引传递给该二维数组时,您将能够获取那些元素,或者相对于您在这里得到真值的元素。好的。所有通过使用此布尔掩码得到真值的元素,那些元素将被提取出来,通过提供该布尔掩码,您可以组合多个条件。所以在这个例子中,我要求给我所有大于 2 的数字,并且相同的数字也必须小于 8。所以我在应用两个条件。这是一个 and 条件。好的。所以再次创建相同的布尔掩码,并且我能够检索大于 2 且小于 8 的数字。有意义吗?现在让我们看看如何操作 NumPy 数组的形状。好的。所以让我在这里创建一个 NumPy 数组。我正在使用 arange 函数。所以它将给我一个包含 1 到 12 的数字的一维数组。好的。并且我将把那个一维数组重塑为二维数组,取三行四列。好的。所以我将重塑。所以我将把一维数组重塑为二维。让我们看看。是的。这就是我得到的。所以如果你想在这里打印这个矩阵。是的。所以这是一个 1D,然后它被重塑为 2D。您需要注意的一件事是,您不能提供任何随机数字。好的。所以这两个数字的乘积必须等于您想要重塑的数组中存在的总元素数。所以这里我正在使用的数组是一个矩阵。它是数组还是矩阵并不重要。但是这两个数字的乘积必须等于这个矩阵中存在的总元素数。所以这个矩阵已经有 12 个元素,3x4 或 3*4 已经是 12。所以这可行。如果我尝试将其设置为六,我会收到一个错误,因为再次相同的错误消息 3x6 是 18,而这不能装入 12 个位置。太棒了。是的。所以您也可以将其重塑为 2x6。所以两行,六列。这做什么?这将采用一个二维矩阵并将其展平。所以展平正是我们在这里做的反向操作。所以展平意味着获取 2D 数组的所有元素并将其放入一维。所以您可以看到这个矩阵被重塑为 2x6,即两行六列,现在它已经被展平回 1D。好的。所以这是原始矩阵,这是展平的矩阵。好的,没问题。所以我只是打印原始矩阵,以便我可以执行转置操作。所以转置做什么?它将交换行和列。所以本质上第一行变成第一列。第二行变成第二列。第三行变成第三列。所以我们有三行。在转置矩阵中我们将有三列。好的。完全正确。所以您可以看到第一列是第一行。第二列是第二行,第三列最初是第三行。好的。所以行和列只是翻转了。让我们看看数据类型以及我们如何处理 NumPy 中的数据类型。所以再次我创建了一个包含数字 1.2、3.14 和 5.6 的 NumPy 数组。您可以看到这些是浮点数。好的。让我打印数据类型。所以它显示 float64。本质上我正在获取我数组中存在的元素的类型。astype 方法将更改数据类型。所以我的原始元素是 float64 数据类型,现在它们被转换为整数数据类型。所以您可以更改数据类型。所以您说获取这个数组并将其数据类型更改为 int64 并将其保存回来。好的。所以您可以看到我的数字是 1 3 5。所以浮点数 1.2、3.14 和 5.6 已被转换为最接近的整数。好的。现在有一些用于算术运算的通用函数。让我们快速看一下。所以您有用于加法、减法、乘法和除法的函数。我有我的数组 X 和 Y。您可以使用这些函数来执行这些操作。而且您实际上也可以直接执行这些操作。但是您必须确保您想要相乘、相除、相减和相加的这两个数组具有完全相同的元素数量。好的,这些是逐元素操作。所以 x + y 有效,x - y 也有效并给出相同的结果。如果您可以看到 x 乘以 y 也是一个数组,也是一个逐元素乘法。您可以看到这个结果与这个结果匹配。同样 x 除以 y 也是一个逐元素操作。您可以看到数组 1 2 3 4 的每个元素分别除以元素 10 20 30 40。所以每个都变成 0.1。完美。您可以默认取对数。所以我又创建了一个数组。这里我有了 np.e,它是数学中的常数 e,指数 e。所以 2.718 值,一个值是 1,另一个值是 100。所以三个值我将用于对数计算。所以默认情况下,这将为您提供以 e 为底的自然对数。e 的值是多少?2.718。所以这个对数的底是这个 e。这就是为什么那个 e 的对数值是 1。好的。log 1 总是 0。所以这就是我在这里得到的。这是以 e 为底的 100 的对数。现在您可以将底更改为 2。在这种情况下,以 2 为底的对数值是这些。所以 e 的对数以 2 为底是 1.44,100 的对数以 2 为底是 6.64,等等。所以这里您将底更改为以 10 为底的对数。所以再次 1 的对数是 0。这是 e 的对数以 10 为底。这是 100 的对数以 10 为底,在这种情况下是 2。所以 np.e 与 np.exp 的幂为 1 相同。您可以使用此函数将一些幂次提升到这个 e。好的。所以值是相同的 2.718。所以指数函数。所以我有了相同的数组 2 3 4。我将使用这个数组作为指数。好的。所以我将使用称为 power 的函数。所以这个数组的每个元素都将在这个例子中被提升到 2 的幂。好的。所以我会得到 2 的平方,即 4,3 的平方,即 9,4 的平方,即 16。所以让我打印这个 4 9 和 16。完美。这些三个数字是什么?这些基本上是指数 e 提升到这些数字的幂。好的。所以这本质上是 e 的 2 次方,e 的 3 次方,e 的立方,这是 e 的 4 次方。您正在使用该数组作为指数来提升一些基本三角函数 sin cos tan。所以我得到正弦,默认情况下这些将计算数字或值,假设这些角度是弧度,请记住。所以 0 弧度的正弦是 0,pi/2 弧度(即 90°)的正弦,sin 90 是 1,而 pi 弧度的正弦本质上是 180°,再次是 0。好的。所以正弦值将是 0 1 和 0。余弦值将是 1 0 1。好的。然后我们也有正切值。您可以看到,然而有些数字不是零。这很有趣,这是因为在这些浮点计算过程中精度损失。好的。所以这实际上是零。这也不是零。好的。好的。任何接近 10^-6 或更小的值都应该被解释为零。请确保。好的。所以这些,这再次是无穷大,这再次是零。好的。同样,我们也有双曲函数。让我们看看舍入函数是如何工作的。我将演示绝对函数、符号函数和舍入函数,如 round、floor、ceil 和 truncate。好的。所以让我再次创建一个数组,我想得到这些数字的绝对值。所以这是负数。所以在绝对值中它将变成正数。这再次是负数。绝对值将变成正数。是的。所以绝对值都是正数。您可以看到,而这些数字在这里有负号,它们由 -1 表示。所有正数都由 +1 表示。现在我想进行舍入。所以舍入函数通过将这些数字四舍五入到最近的十进制位,最近的整数,让我们说。所以最近的整数将是 -2。最近的整数将是 0。最近的整数将是 1。最近的整数将是 2。最近的整数将是 3。让我们看看。是的,正确。所以 floor 会将值向下取整到较低的整数。好的。所以 ceil 会将值向上取整到较高的整数。好的。truncate 会简单地排除小数点后的值。所以 75 将被忽略。22 将被忽略。58 将被忽略,等等。好的。所以这就是您获得这些数字的方式。符号将被保留。然而,现在让我们看看一些比较和逻辑通用函数。我再次有了我的数组 1 2 3 4 和 22 222。所以,我实际上可以比较 A 的每个元素是否小于 B 的每个元素。这再次是逐元素工作的。在这里,您正在检查 A 的每个元素。它是否大于 B 的每个元素?您再次检查 A 和 B 中相应元素的相等性,而不是相等性。好的,让我看看。好的。现在也可以通过说 a < b 来简化这些。这也可以。您可以看到结果非常相似。好的。对于相等性,您可以转到 2 * 等号。所以您正在检查相等性。这个结果应该与这个相同。好的。对于不相等性,这应该写成这个感叹号等于。所以这不等于 b。您可以看到结果,大于等于可以写成大于等于 b。所以这个结果将再次与这个相同。同样的事情在逻辑格式中。好的。好的。现在统计和聚合函数。我创建了一个简单的 1 到 9 的数字数组,二维格式。所以我想计算所有元素的总和。所以 np.sum 函数,所有元素的总和从 1 到 9。好的。这里的平均值,所有元素的标准差,以及所有元素的方差。好的,整个数组。所以总和是 45,平均值是 5,标准差是 2.58,方差是 6.6767。类似地,我想得到最小值,最大值,最小值的索引,然后是最大值的索引。这就是 arg 的意思,它是 argument 的缩写。所以它将分别给出最小和最大值的索引。所以零,这是第一个元素,八是最后一个元素。无论如何,我们还可以得到中位数。所以所有九个数字的中位数是 5,第一个四分位数是 3。好的。您可以更改这里的四分位数。0.25 将给出第一个四分位数,0.5 将给出中位数,0.75 将给出第三个四分位数,1 将给出最大值。0 将给出最小值。所以这是任何数据的一个五点摘要。您还可以沿特定轴进行求和。好的。所以这意味着什么?如果您想沿行求和,您可以将轴指定为 1。如果您想沿列求和,那么您可以将轴指定为 0。您想如何求和?如果您想将所有数字的总和加起来,那么您不必指定轴参数。它将默认获取所有元素的总和。但是如果您想沿行或列求和,那么您必须提供轴参数。现在让我们快速看一下广播概念,它允许在不同形状的数组之间执行数学运算,遵循一定的规则。让我们看看。所以我有一个简单的 NumPy 数组,1 2 3,我将向该 NumPy 数组添加一个标量。好的。所以发生的是这个标量被间接类型转换了。它在后台被转换为另一个数组,然后复制三次。所以您得到一个像 10 10 10 这样的数组,然后该数组 10 10 10 被添加到这里的每个元素。所以加法运算仍然是逐元素进行的。所以后台创建这个额外的数组 10 10 10,这正是广播实际所做的。如果您看到这将创建一个三行一列的数组。所以它本质上是一个列向量。所有数字都在一个维度中。好的。这是一个一维数组。所以这是一个二维数组,这是一个一维数组。好的。您想将一个一维数组与一个二维数组相加。所以再次您将不得不使用广播的概念。所以这是它的工作方式。让我们看几个线性代数函数,它们非常重要。我创建了两个二维矩阵 1 2 3 4 和 2 0 1 2。A 和 B。我将相乘 A 和 B。所以请注意,A 乘以 B 不等于 B 乘以 A,因为矩阵乘法,它是使用 @ 运算符完成的,它不是逐元素操作。好的,让我展示一下。所以这些是 AB 的值,以及 A 和 B 之间的矩阵乘法。所以这是 A 乘以 B。这是矩阵乘法。让我们看看 B 乘以 A。它得到什么?好的。所以 B * A 是这个。A 乘以 B 是这个。所以这正是我所说的。A * B 不等于 B * A,因为这些不是逐元素乘法。好的。您也可以通过使用这个函数 A.dot(B) 来执行相同的操作。所以结果将与我们之前得到的结果相同。好的。所以您可以使用 dot 函数。您还可以使用 matmul 函数。所以,np.matmul(A, B) 矩阵乘法 A, B 再次确保您传递参数的顺序。所以这又是 A 乘以 B。如果您说 B, A,那么这将是 B 乘以 A。您可以使用线性代数模块来获取逆矩阵和行列式。好的。所以这是 A 的逆矩阵和 A 的行列式。我将使用 random 模块来生成一些数字和序列。所以我想生成随机整数,在这种情况下。最低值为零,最高值为五,我想选择五个数字。好的。所以这些是我得到的数字,这些数字也可以重复。好的。所以随机地,我通过替换选择五个数字。好的。所以我会得到这个数组。好的。这里我正在创建 0 到 1 范围内的随机数。零是包含的,一是不包含的。好的。所以它在一侧是开区间。我将在该范围内创建五个随机数。所以这些是您得到的五个随机数。如果您愿意,您也可以对这些随机数进行四舍五入。所以让我将其四舍五入到小数点后两位。所以您可以看到生成了随机数,并且也四舍五入到小数点后两位。我还可以创建正态分布的随机数。位置是随机数的均值。尺度是标准差,大小意味着您想要创建多少个随机数。好的。所以 size 决定了您想要多少个数字。并且这五个数字的平均值将接近零。它不能保证它会正好是零。并且这五个数字的标准差将接近一。这里是您的数字。好的。您还可以进行打乱。所以,让我们
说我有一个包含这五个数字的数组,我想打乱它们。所以这是打乱后的数组。在这里,你并没有生成任何东西,而是生成了另一个数组,其中包含从前一个数组打乱的数字。你也可以创建这些数字的随机排列。好的。好的。所以总而言之,在这个Jupyter笔记本中,我演示了如何使用内置的numpy函数创建不同的数组。我们已经做了足够多的关于索引、切片、形状方面的数组操作、重塑函数。我们还使用了像算术运算这样的展平函数。我们已经做了对数三角函数。以及四舍五入函数、比较和逻辑运算。我还演示了广播和线性代数函数。最后,我们还看到了一些随机生成器函数。谢谢。大家好,欢迎来到这个关于matplotlib基础实践的课程。所以在这个笔记本中,我将演示matplotlib中最常用的绘图函数以及如何自定义这些图。那么,让我们开始吧。所以首先我们需要安装matplotlib,如果还没有的话,可以使用pip install matplotlib。大多数Anaconda安装都预装了matplotlib,你的Colab也预装了matplotlib。所以让我看看我机器上matplotlib的版本是3.1。好的。现在,让我们从matplotlib导入pyplot模块,并将其别名为plt。所以pyplot主要用于一维绘图。如果你想进行二维或三维绘图,你有不同的模块。我还导入了numpy作为np,以便创建一些将在matplotlib中实际绘制的数组。现在,在早期版本的Jupyter笔记本中,你必须取消注释这一行并运行这个matplotlib in-line,以便图表出现在Jupyter笔记本中。但如果你运行的是最新版本的Jupyter笔记本,或者甚至使用Google Colab,这实际上已经不再需要了。好的。所以,为了向后兼容,我暂时保留它。所以,让我用numpy函数linspace创建一个样本数据,即从0到2π线性间隔的数字,包括两端。我将在中间创建98个数字。所以起始和结束数字都包含在内。所以我要创建的数组中的总数字是100个,我计算这些x值的正弦值,并将其保存为y。所以我有x和y。你可以看到y值。让我打印y值。所以sin 0是0,sin 2π 2π是360°,也接近于零。对吧?所以这应该被解释为零。我说这不是一个有效的数字。我会说sin 2π,也就是180°,在数学上,在任何高中课本中都会给出零。所以这实际上是零。好的。所以,首先我们将在这里看到一些基本的图表类型。我们将首先从折线图开始,然后是散点图、条形图、直方图、箱线图和饼图。所以,让我们先从折线图开始。好的。所以,我首先创建图形画布。你可以在上面看到这个图形将被绘制。我正在设置纵横比。比如6英寸x 4英寸,我正在创建一个画布。所以图形的纵横比可以设置为4x4、6x6。这些是方形的形状,而这将更像一个矩形形状,图表将在其中可见。要创建折线图,我有一个plot函数。你必须提供x轴上的值,然后是y轴上的值。这是两个位置参数,然后你有一系列关键字参数。所以你想给图例中的图表起什么标签?所以这个标签会出现在图例中。线的颜色应该是什么?好的,默认情况下它会有一种蓝色的颜色。但如果你想明确指定颜色,我们将看到如何更改颜色。然后是线型。所以线型是破折号。破折号意味着你将得到一条实线。线的宽度在这里被指定为两个像素。好的。所以你可以改变线宽。好的。所以默认是1。这里线型默认是破折号。颜色是某种蓝色,不是你在这里看到的精确蓝色。默认情况下没有标签。好的。所以标签是None。所以我指定了一个标签和所有自定义值。所以这将是图表的标题。标题出现在图表画布的上方。所以,让我执行它。你可以看到这是正弦波的折线图标题。这被称为y标签。所以你想在y标签中写什么?好的,这些是y轴值。同样,你看到这是x标签。好的。所以我在这里提供x标签和y标签。如果你想增加字体大小,你可以使用fontsize参数来实现。所以,让我有一个字体大小,比如12。我将增加标题的字体大小。比如我想选择15。所以你现在可以看到,与刻度标签相比,这些尺寸稍微大一些。这些是我的刻度标签,你可以看到这些是刻度。所以0、1、2、3、4、5、6这些是刻度标签。同样,你看到的这些数字是y刻度标签。好的。所以默认情况下,它们的字体大小是10。所以我把标签设为12。这个标签是12,你可以看到这条线宽是2,这个字体大小是15。好的。你也可以自定义。所以,比如我想把这个颜色改成dodger blue。DODGER。Dodger blue。我最喜欢的颜色之一。你可以看到一种非常漂亮的浅蓝色。所以你可以,你知道,创建各种各样的异国情调的颜色。你想用亮绿色。好的。所以绿色是一种颜色。亮绿色是另一种颜色。好的。所以,让我删除它。这是普通的绿色。这是亮绿色。好的。所以,你在哪里找到这些名字?好的。所以,让我们去谷歌搜索matplotlib命名颜色。好的。所以点击第一个链接,这里就是。这些是你可以在代码中提供的颜色的名称。好的。所以我当时正在使用这些颜色,这个dodger blue。你能看到吗?还有一种绿色,亮绿色也应该在某个地方。是的。所以这是亮色,亮绿色也应该在某个地方。好的。然后你有多种深浅的粉色和红色。好的。Crimson、deep pink、hot pink、magenta等等。Purple、dark magenta。你可以提供这些名称中的任何一个。所以,回来。所以,这就是你可以改变颜色的名称的方式。现在是线型。现在,而不是破折号,让我给它双破折号,它会给我一个虚线。好的,你可以看到,抱歉,一条虚线。这是一条虚线。好的,要得到一个点线,你可以使用冒号。所以这给了我一个点线。你可以非常清楚地看到这是一条点线,你也可以使用点划线。所以点划线也应该在那里。好的。所以那是破折号点。好的。所以是破折号和点。所以,我们在哪里搜索这些线型?所以,再次去谷歌搜索matplotlib线型。点击第一个链接,你可以看到matplotlib中所有可用的线型。所以,这些是最常见的。同样,如果你想要更多异国情调的线型,你可以尝试这些高级选项,但这些是最常见的。破折号是实线。你可以得到一个点线、破折号线和点划线。好的。所以,你可以看到这些线看起来是什么样的。完美。所以,再次回来。所以我已经教了你如何自定义字体大小、颜色、线型,甚至可以改变线宽。所以,如果你愿意,你可以把它设为三,它会变成更粗的线。你可以看到线粗已经增加了。好的。所以,你可以根据需要自定义。好的。然后这个legend函数实际上会将这个图例放置在图表中。所以,如果你忘记在这里提供图例,你可以看到这个图表代表什么,这是由图例给出的。好的。所以,图例已经消失了,因为我注释掉了它,你也可以提供图例的位置。所以,图例中的值是由标签自动填充的。所以,如果你有多个图表,确保每个图表都有一个标签,因为你没有在legend函数中明确提供任何文本。好的。所以,建议每个图表都必须有一个相应的标签,这样matplotlib才能识别出这些图表的标签是什么,如果你在同一个画布上有多个图表。好的。所以,比如我想把位置从第一象限,这是我的第一象限,移到第三象限。这是第二象限。这是第三象限。所以,我会这样做,loc OC等于3。所以,它会将位置改变到第三象限。现在你可以看到位置从默认的第一象限移到了第三象限。所以,matplotlib实际上会选择最佳位置,这样它就不会与图表重叠。所以,这种智能是matplotlib拥有的。好的。它已经处理好了。但仍然,在某些情况下,如果你想指定位置,你可以继续这样做。好的。你可以提供数字,也可以提供文本。好的。所以,位置可以提供为文本。你可以看到它支持这些字符串,左上角、右上角、左下角和右下角。它也支持中心。所以,默认情况下,它会选择最佳位置。好的。这样它就不会与你的实际图表重叠。好的。所以,让我们继续。所以,这次我再次有一个二元图。让我创建两组随机数,x和y,然后再次创建图形画布,将x值和y值提供给scatter函数。然后颜色应该是C等于表示颜色。所以,颜色的缩写是C。所以,标记的颜色应该是多少?标记的样式应该是多少?好的。以及这些标记的不透明度级别应该是多少?所以,让我们先看看图表。所以,你可以看到这里有红色的标记。如果我将alpha设置为1,我将得到深红色。如果我将值减小到0.2,你可以看到它们是浅红色。所以,它变得更加透明。所以,较低的值会导致更透明的标记。所以,如果有一些重叠的标记,你仍然可以看到它们。好的。所以,你可以自定义不透明度、标题、标签以及那些东西都是一样的。这里的新东西是网格。好的。所以,网格是你的这些垂直线和水平线。这些被称为网格。好的。在之前的图表中,我们也有网格。好的。如果你不想显示网格,你可以将其设置为false,网格将不会显示。你可以看到这些垂直线和水平线,它们帮助我们跟踪值。它们已经消失了。所以,你可以根据你的选择和用例来定制。所以,plt.show()将最终显示该图表。好的。所以,这应该是任何包含图表代码块中的最后一个matplotlib函数。好的。所以,这里matplotlib中的最后一个函数也是显示图表。好的。所以,它首先在内部创建图表,进行各种自定义,最后显示它。好的。所以,这就是我们将对所有其他图表遵循的哲学。好的。所以,在线图表中,比如你也想提供标记,这是可能的。好的。所以我又回到了实线。现在,让我提供一些标记。好的。所以,这里如果你愿意,你也可以提供标记。标记等于,比如我想用方形标记。好的。这次我将写S。S代表方形。好的。好的,让我们看看我得到了什么。你可以看到在所有这些x值处都有方形标记。现在我有100个x值。所以,我得到了这么多方块。好的,这些是这么多方块。所以,S代表方形。这里O代表圆圈。好的。所以,还有其他标记样式。所以,让我们再次去谷歌搜索matplotlib标记。好的。所以,你会在文档中找到标记参考。所以,你可以看到这些是实际的样式,你将在代码中提供,这就是它在图表中实际显示的方式。好的。所以,你可以有一些数字。八边形、五边形、正方形。所以我刚才用了这个正方形。你也可以选择五边形、六边形、星号等等。好的。所以,这些都是我们可用的标记。好的。好的。所以,让我们继续下一个图表。好的。所以,让我们看看如何创建条形图。条形图是用于分类数据的。好的。所以,对于数值数据,你可以使用折线图,甚至散点图。但如果你的x轴上有分类数据,好的。所以,ABCD会在你的x轴上,它们的计数或频率由这里的值表示。好的。所以,现在这个ABCD可能代表你数据集中客户的职业。好的。所以,这个A可以是学生,B可以是受薪的,C可以是退休的,D可以是无业的。然后这是具有相应职业的客户的实际计数。好的。它也可以像性别一样简单。它也可以是A B可以是男性女性,然后是男性女性的计数。好的。所以,你可以有任意数量的类别及其相应的频率或计数。所以,这就是类别和值的意思。所以,我再次创建我的图形画布。所以,这次我将使用bar函数。类别,即x轴值,将由类别填充。y值将作为计数。条形的高度将由值控制。记住这一点。好的。然后这些条形的颜色应该是多少?让我们来看看。所以,这些条形的颜色肯定是绿色的,因为这是我在这里提供的颜色。然后是标题、标签。这些是我们已经看到的相同函数。好的。所以,这些是任何matplotlib图表的通用函数。所以,x轴标签、y轴标签和标题中应该写什么?好的。你也可以创建堆积条形图。好的。所以,如果你有多个类别,你想同时创建两个分类数据,你也可以选择堆积条形图。好的。同样,直方图是用于单变量数据的。好的。特别是如果数据是数值的。好的。你想提供,或者你想可视化数据在多个值区间上的分布。好的。所以,你可以提供x轴上你想要的区间数量。默认的区间数量应该是10,然后是用于绘制直方图的数据,然后是直方图条形的颜色,然后是不透明度级别,以及边缘颜色应该是多少。所以,在之前的图表中,你也有一个提供边缘颜色的选项,等等。好的。所以我再次创建了1000个具有正态分布的随机数。randn函数。N代表正态分布。好的。所以,随机分布的数字来自正态分布。好的。所以,你可以看到目的。条形图和直方图之间的主要区别是条形图是离散的。总会有一些间隔,因为这些是离散值。好的。A B C已经。好的。这是分类数据。这就是为什么你总会在条形图中看到间隔。这是连续数据。所以,你永远不会有间隔。好的。这是连续数据。你不能混用。好的?所以,你不能将条形图用于连续数据,也不能将直方图用于分类数据。那没有意义。现在,让我们看看箱线图。我们想先创建三个numpy数组。在这里,我将使用normal函数来创建这些numpy数组,这些是正态分布的值。所以,0是位置,也就是均值的位置。所以,数据一的均值为0,标准差为1。我将有100个数据点。第二个数据数组的均值为5,标准差为2。第三个的均值为-3,标准差为1.5。好的,所有三个都将有100个值。再次,创建一个图形和一个箱线图。所以,我只是将这三个组合起来,并提供一些刻度标签。让我们看看箱线图是如何出现的。好的。所以,你可以看到这些线代表中位数。好的,这些橙色线,它们代表中位数。你有下须和上须。这是盒子的边缘。下边缘代表第一四分位数。这是第二四分位数。中位数。这是第三四分位数。好的。对于任何箱线图。所以,盒子的总高度将由四分位距Q3 - Q1给出。好的。其他两个图表也是如此。好的。所以,再次这是我的Q1值、Q2值和Q3值。你有这个须的总长度是四分位距的1.5倍,也就是盒子长度的1.5倍是这里的总高度。还有一些你看到的异常值,它们超出了上限。好的。所以,否则,如果没有圆圈在上面和下面,那么这些水平线将代表最大值和最小值。所以,这里它代表最小值。再次,这是最小值,这是分布中的最大值。但这里的最小值由圆圈表示,而不是这个,因为我们有值在水平线以下。所以,水平线不能是最小值。对吧?所以,这是最小值,这是最大值。所以,你可以在箱线图中获得关于分布的所有信息。好的。我们也可以使用饼图。所以我创建了一些切片。所以,让我们看看切片标签A、B、C和D。然后这基本上是你圆所占的比例。所以,40%的圆将被A占据。另一个25%由B占据。C将占据20%20%,最后15%由D占据。所以,确保它们的总和等于100。好的。这里有一些有趣的事情。我为第二个切片设置了一个偏移量,所以第二个切片看起来有点偏离。好的。所以,这是爆炸效果,它被突出显示了。基本上,如果你想突出显示一个特定的部分,你也可以这样做爆炸选项。所以,这里使用的主要函数是pi。你可以提供切片。好的。然后是切片标签,爆炸选项。如果所有默认值都是零,意味着你将得到一个扁平的饼图。所以,这个爆炸选项本质上给了你一个3D效果。然后是标签格式化,这是通过这个完成的。好的。然后,你是否想要阴影。所以,你可以看到这里的阴影。阴影已经给出。所以,你是否想要阴影效果。所以,它给了我一种3D效果。然后是起始角度。好的。140,或者你可以提供0、90,任何角度。所以,你的切片从哪里开始。好的。所以,看看这里的角度,从这里到这里,那是140°。好的。这个角度是140°。所以,第一个切片从那里开始,然后是第二个,然后是第三个,最后一个。现在我们已经看到了如何自定义其中一些内容,让我们深入研究自定义轴限制、文本网格线和图形大小等。好的。所以,我再次创建了一个图形。我将在这里创建两个图。你看我提供了两个不同的标签sinx和cosx。所以,请确保如果你在同一个画布中有多个图,请提供不同的标签,否则matplotlib将不知道,你甚至无法弄清楚哪个图对应于哪个函数。好的。所以我使用了两个函数。好的,我的x值已经创建好了,然后你可以指定你想要的颜色和线型。好的,没问题。标题、x标签、y标签、图例,我 Everything都解释过了。网格和显示。让我们来看看。是的,所以我的正弦是实线,余弦是虚线。同样,如果你愿意,你可以设置x轴和y轴的限制。所以,这里我有了相同的图xy,颜色是红色的,我正在设置限制。所以,0到2π。所以,2π将是,π是3.14。所以,2π将是6.28。好的。所以,这就是我设置的限制。对于y限制,你可以看到这些是正弦值和余弦值。所以,默认情况下,每个人都知道正弦和余弦的限制是从-1到+1。这就是为什么最小值是-1,最大值是+1。你可以改变这些值。所以,比如我想从-2到,所以,比如我想从-2到+2。好的。所以,我正在设置y轴的限制。所以,现在你可以看到这是-2,这是+2。好的。如果你想看到标签-2和+2,稍微增加一点。是的。所以,现在你也可以看到标签了。好的。所以,你可以提供y限制应该是多少。同样,如果你想获得一个更窄的x限制,也可以做到。好的。所以,这里我从0到2π。比如,你想只绘制从0到π。也可以做到。好的。所以,你只需要改变这里的数字。好的。所以,在哪些点你想有刻度。所以,默认情况下,matplotlib决定我想把刻度放在这些地方。好的。然后标签也自动填充。但如果你愿意,你可以提供x轴上刻度将被放置的实际点以及相应的标签。好的。所以,你现在看到只有在0、π和2π处有刻度,标签也以你在这里给出的数学符号表示。好的。所以,你也可以以这种格式提供标签。让我复制一下。好的。如果你想让你的标签有科学计数法,你也可以这样做。所以,你可以使用美元符号$2,然后反斜杠写pi,这将是相同的美元符号反斜杠2pi。好的。哦,抱歉,我错过了美元符号的闭合。好的,那是错误。好的,你可以看到,不要忘记关闭这个美元符号。所以,美元符号开始和关闭,再次美元符号开始和关闭,在其中你可以提供数学符号。好的。所以我在这里提供了数学符号pi。所以,这是另一种你可以做的方式。所以,你可以看到用数学符号写的pi。好的。你可以提供任何其他数学符号。所以,如果你想用sigma,让我们看看sigma是如何出现的,等等。你可以用alpha、beta、gamma、delta。所有类型的数学符号你都可以在标签中拥有。这就是它的工作方式。好的。现在,让我们看看如何处理多个图,即通过创建多个图、多个轴,甚至子图。好的。所以,我在这里使用plt模块的subplots函数。多少行?我有一行两列。所以,它们将并排显示两个图。图形画布的总尺寸是10+4。好的。在第一个子图中,所以这些是子图的索引。所以,0表示第一个子图的索引。然后这是普通的图。然后是那个特定子图的标题。好的。这次函数从plt.title变为axis0,即那个特定子图的索引,这将变成set_title函数,这是我们在这里应用的对象编程概念。第二个子图也是如此。所以,首先引用第二个子图的轴,然后是普通的绘图函数,然后第二个子图也是如此,引用第二个子图,然后就是你提供的标题。好的,suptitle是超级标题。基本上,这将是提供在两个子图顶部的标题。好的。tight_layout将修剪图表边缘的任何多余空间。如果有额外的空间,将被修剪,这就是tight_layout。让我们看看。所以,这是我得到的结果。如果你想让它们一个接一个地显示,那么你必须使用另一种表示法,即,比如我想有两行,我会把这个改成2,我想有一列,所以两行一列将得到一个接一个的。好的。所以,在这种情况下,我可能想用6x14,让我们看看,太大了,所以6x10应该没问题。是的。所以,你可以看到,所以高度是14,宽度是6。好的。所以,你可以自定义这个。然后,你也可以创建多个图形。好的。所以,这是一个图形,然后是另一个图形,或者如果你想把两个代码放在一个框里,你会得到两个图形背靠背。好的。你会得到两个图形背靠背,因为我们有两个plt.show()函数。所以,两个图形都背靠背地创建在同一个画布上。所以,你为每个图形创建了画布。好的。所以,你也可以这样自定义。如果你想让它们并排显示,那么最好使用子图,或者如果你想让它们一个接一个地显示,那么你也可以使用这个选项。好的。然后我们有样式。你想如何显示子图的背景,那就是样式。所以,默认情况下,我们的语言使用ggplot选项。所以,你也有其他的样式表,比如seaborn、bmh等等。所以,让我们使用我们语言中可用的默认ggplot。所以,ggplot样式表。所以,我再次创建我的图形,图表,x轴值,y轴值。我正在创建一个散点图,这是我们这里的新东西。我正在创建一个注释。注释将有助于精确地指出图表中的一个点并为其提供标签。好的,那就是annotate函数。所以,这是标签中出现的值。所以,这是箭头的x和y坐标。你基本上在创建一个箭头,这是箭头末端的标签,你可以这么说。所以,这是文本开始的地方,然后是箭头属性,你想要的颜色,以及你想缩小或扩大箭头的长度。这些自定义中的一些可以在文档中找到。现在,这些是其他常规的东西。所以,你可以看到,我能够通过使用这里的箭头来突出图表中的一个特定点。所以,这是我在注释中提供的标签。好的。你也可以在图表的任何地方放置一个常规的文本框。好的。所以,那个函数是不同的。那是plt.text函数。好的。所以,你可以看到背景颜色等等是不同的。如果你愿意,你可以将ggplot改成,比如seaborn或bmh。所以,让我们继续看看线型样式表。所以,matplotlib样式表。好的。所以,我们在这里有matplotlib的样式表参考。所以,这是我们使用ggplot选项的方式,这些是其他的。所以,这是默认的。这就是我们一直以来使用的,然后我们将其更改为ggplot。所以,一旦你改变了样式表,该样式表将对剩余的笔记本保持活动状态。除非你将其设置回默认值。所以,这是经典的solarized light bmh。这就是bmh中的图表的样子。你可以有深色背景、浅色背景、538、ggplot、灰度,然后你有seaborn v08版本,彩色亮色暗色调等等。好的。所以,是的,等等。所以,让我们回来。让我把它改成bmh,看看图表如何变化。是的。所以,背景肯定改变了。好的。所以,回到ggplot。好的。你可以这样恢复到默认值。如果你想保存你的图表怎么办?然后你可以使用名为savefig的函数。好的。并提供图形名称。你可以提供深度。DPI是每英寸点数。所以,每英寸300点。默认情况下,它是72。所以,如果你增加这个值,你将得到一个更高分辨率的图像。当然,这也会占用更多空间。好的。保存的图形大小也会更大,以字节、千字节为单位,再次是box inches,即我们将创建的tight_layout。好的。所以,这确保了图形周围的白色空间最小。好的。所以,让我们创建这里的图表。我创建了这张图,还没有保存。你可以看到它还没有保存。但如果我想保存它,我会取消注释并再次执行它。好的。我们可以验证它已经保存了。所以,让我回去,你可以看到它是在11秒前创建的。好的。所以,我正在一些云平台上运行它。否则,你可以下载它,它将保存在你的本地驱动器上。如果你在Anaconda中运行它,它将保存在你的本地驱动器上。好的。所以,这是保存的图。完美。所以,相当高的分辨率。你可以看到它没有模糊。你可以看到,即使我放大很多,它也不会模糊,因为它分辨率很高。300 dpi实际上是很多。好的。所以,默认值我认为是72。好的。所以,最后是一些快速提示。所以,你可以使用子图进行多个可视化,而不是将多个图堆叠在一起。好的。一个接一个。所以,你可以将你的图表组织成一个网格,2x2、3x2、2x3之类的网格。好的。请正确标记你的轴,并在图例中放置正确的标签以示清晰。如果你在同一个画布中有多个图,请使用样式和颜色来创建视觉上吸引人的图表。好的?并确保你的标记清晰可见。如果你有标记和线条,你必须在同一个画布中的多个图和多个标记之间有一定的对比度。好的。所以,通过界面跟踪图形和轴。基本上是子图的编号。好的。所以,我们在这里创建了子图。所以,子图的编号将由这个函数决定。好的。当然,正如我们为命名颜色列表、matplotlib线型、标记甚至样式表所引用的那样,请在文档中查看高级功能。好的。所以,我在这里组合了几个图表类型。所以,我这里有散点图,你可以看到,还有一个折线图。所以我只是创建了一些合成数据。所以在一个图中,我有散点值以及折线图。并且通过正确使用图例,我能够清楚地演示这是一条线。这条线代表什么?你可以说它代表了一个趋势。而这些是我的观测数据点。所以在你的现实场景中,这些将是你的观测值。而这条线不会是一条合成线。它将是一条从回归模型中得到的线。可能是线性回归或其某种变体。然后你有你平常的标题XL有价值的数值。好的。所以,只是一个快速的结论。所以,我们在这个笔记本中看到了matplotlib如何进行基本绘图。我们涵盖了不同类型的图表,如折线图、散点图、条形图、直方图、箱线图,甚至饼图。我们对标签、图例、样式和标记、颜色、标记样式等进行了不同的自定义。我们有多个图。如何将图表保存到硬盘,我们甚至在最后一个例子中看到了如何组合多种图表类型。好的。所以,这就是关于matplotlib的代码演示。所以,什么是pandas?你可能在想。Pandas是一个流行的Python开源库,用于数据操作和分析。Pandas提供了强大的数据结构,我们将看到它们是数据框(DataFrame)和系列(Series),它们用于轻松地存储和操作大型数据集。使用pandas,你可以从各种来源加载数据,如CSV、Excel,甚至SQL数据库。你也可以清理你的数据集。你可以重塑它们。你也可以使用pandas中内置的各种函数非常快速地分析这些数据。所以,让我们开始吧。如果pandas没有安装,你可以取消注释这一行并安装pandas。最有可能的是,如果你使用Google Colab或Anaconda环境,pandas会预装。所以,我有一个代码在这里,它指示pandas忽略任何警告。警告与错误不同。好的。所以,首先我们将看到如何导入一个CSV格式的数据文件。CSV是逗号分隔值文件。所以我有一个churn prediction.csv文件。我将把它导入pandas。所以,我们将使用read_csv函数来做到这一点。好的。一旦我们读取了CSV文件,我就将其存储为数据框的形式,并显示该数据框的前五行。所以,它看起来是这样的。所以,数据框。所以,数据框对象基本上是二维的,就像你有几行和几列一样。好的。所以,它是二维的。而数据框的每一列本质上是Python中的一个系列。好的。所以,这是一个系列。这是另一个系列。这是另一个系列。事实上,这个数据框的每一行。所以,你可以取出任何一行。比如这一行。这一行也将被视为一个系列。任何一行或任何一列都将是一个系列。所以,系列本质上是一维的,因为它是一行或一列。而数据框是二维的,因为它将有m行和n列。所以,让我们看看这个数据框有多少行和列。所以,让我们看看df.shape。所以,这个数据框有15,929行和21列。你可以通过滚动查看所有21列。好的。所以,为了在这个笔记本中进行简单的分析,我们将使用我将要创建的一个简单的数据框。好的。我还将导入numpy和random模块来创建一些随机数。好的。所以,我将pandas导入为pd,这是我分配给pandas模块函数的别名。numpy被导入为np,这是numpy的别名。我导入了random模块。好的。所以,我正在固定这个随机数的种子。好的。这确保了数据的一致性,这样每次运行代码时都会得到相同的数据框。好的。所以我这里有一些名字和它们对应的性别,我将创建一些年龄值,8个介于21到25之间的随机数。你可以改变这个范围。我还将创建这三个科目的分数。好的。所以,总共8个科目的值,8个分数范围在60到95之间。最高是95,最低是60。然后是列表推导式。这是一个列表推导式。如果你看到这个,这也是一个列表推导式。这也是。所以,这些列表将被提供给这个字典。所以,这是一个我正在创建的字典。这是键,这是值。所以,值都是列表。好的。所以,names是一个列表,来自所以,names是一个列表,来自这里。Genders又是来自这里的列表。Age是另一个来自这里的列表。Marks是另一个列表,它再次来自这里。最后,subjects也是一个列表,它来自这里。好的。所以,我用这五个键填充了所有五个列表。所以,让我执行它。我最终传递了一个字典,从这里到这里是一个字典,你可以看到这个花括号。所以,这个字典现在被转换成一个数据框对象。所以,这是我的数据框,我有名字、性别、年龄、分数和科目。好的。所以,如果你想看看有多少行和列,我们可以看到df.shape。所以,我有8行5列。我有一个快速的统计摘要。好的。所以,统计摘要只会处理数值列。我只有年龄和分数是数值列。其他三列,即姓名、性别和科目。这些是分类列。所以,这就是为什么它们不包含在这个摘要中。好的。所以,在这个摘要中,我有什么?我有计数。该列中有多少值?该列的平均值。所以,年龄值的平均值是23.375岁。平均分数是78点多。标准差,我的最小年龄是21。最大年龄是25。50百分位数是中位数。这里也是一样。64是最低分数。最高是91。中位数分数是77。这些是第一个四分位数。这是第二四分位数,也就是中位数。这是第三四分位数。这是第四四分位数,也是最大值。如果你愿意,你也可以将这些值四舍五入到,比如两位小数,以便于查看。同样,如果你想获得分类列的统计摘要,你可以使用describe并包含object类别。好的。所以,我在姓名中有8个唯一值,在性别中有2个唯一值,在科目中有3个唯一值。所以,最上面的,对于姓名来说,这无关紧要,因为所有姓名都是唯一的。但对于性别,我最频繁的值是男性,频率为5,我的数据框中最频繁的科目是统计学,频率为4。让我们通过使用info函数来快速了解这个数据框的信息。所以,info函数给了我数据框的快速摘要。8个条目意味着有8行。总共有5列。所以,你还可以获得关于行和列的信息,以及每列中有多少非空值。你还可以看到每列的数据类型。所以,如果你看到name是object数据类型,gender也是object数据类型。Subject是object数据类型。这就是为什么我在这里使用object来获得统计摘要。好的。其他两个是整数。所以,年龄和分数,它们是整数。所以,你实际上可以通过info函数查看每列的数据类型。现在,让我们看看如何选择和过滤数据。好的。比如,我想只选择我的数据框中的分数列。所以,这是一个系列。你还记得我的数据框的单个列将是系列。让我们检查数据框的数据类型。首先显示pandas.core.frame.DataFrame。如果我对我的type和df.marks做同样的事情,你可以看到这里的数据类型是Series。本质上,这意味着这是一个系列,而整个数据框,这是我的数据框,它是2D的。现在,让我们做一些条件索引。好的。所以,你也可以选择多列。好的。所以,让我向你展示如何选择多列。这里我只选择了一列marks,但比如你对查看两列感兴趣。一个是姓名,另一个是分数。所以,如果你注意到我传递的是一个列名列表。一个列名列表。好的。对于单列,你不必使用列表。但如果你想,但如果你想从数据框中提取多列,你需要将它作为列名列表传递。现在,比如你想只显示那些行。这是你的完整数据框。现在你想只显示那些行。好的,其中分数大于80。所以,本质上,如果你想手动检查分数大于80的地方。所以,这个大于80。这个大于80。这个。好的。所以,你应该只得到三行。让我们验证一下。所以,是的,这三个学生的分数都大于80。所以,这就是如何根据列名选择行。好的。或者根据对列应用的条件。如何选择一些行?要选择行,你需要使用loc和iloc函数。好的,让我们看看。所以在我们理解loc和iloc的概念之前,让我们先理解标签。所以,在一个数据框中,这些是我的列标签。这些是我的列标签,这些是我的行标签。所以,你看到的粗体是标签。数据框的列和行也有索引,默认情况下。所以,默认索引从零开始。所以,这是零。这是1、2、3和4。所以,subject的索引是4。age列的索引是2。name列的索引是0。同样,这些是我的索引。好的。所以,默认情况下,行标签和行索引是相同的。这些是我的索引。这些是索引。记住,蓝色的那些是索引。行索引和列索引。好的。所以,你可以使用loc方法,通过提供标签来获取行。你可以使用iloc方法,提供索引来获取行。所以,你可以通过使用它们的标签或索引来获取行。好的。如果你想提供行的标签,你应该使用loc方法。如果你想使用行的索引,使用iloc方法。所以,基本上是基于索引的位置。所以,让我们看看输出。所以,这是第二行。你可以看到Sophia Smith,女性,22岁,78分,Python。同样,你想看第三行。所以,第三行,这个2基本上是索引,而这个实际上是标签。好的。所以,正如我刚才提到的,默认情况下,行的标签和索引是相同的。所以,现在这些数字之间没有区别,但Python知道你使用的是什么函数。所以,loc意味着它将假设你提供的数字实际上是一个标签,而iloc意味着你提供的数字是一个索引。好的。所以,0、1和2。所以,这些是,所以iloc函数的另一个优点是,你可以使用iloc函数来使用多个,来获取多个行和列。所以,比如我想获取前五行。冒号表示从开始到结束,在五之前停止。所以,索引0、1、2、3、4。这是IO,记住。所以,索引位置从0到4。所以,0到4,我得到了。是的。同样,你也可以获取列。所以,df.iloc,比如你想获取所有行和前三列,这是可以做到的。所以,所有行和前三列。所以,0、1和2,因为它是索引位置。所以,它会在3之前停止,也就是2,0、1、2。所以,这是0、1和2。好的。你也可以使用关键字,比如-1。所以,df.loc.iloc。所以,我想获取最后一行。所以,最后一行意味着-1。所以,这是你的最后一行。同样,如果你想获取最后一列,也可以做到。所以,最后一列是df.loc。所以,在这种情况下,最后一列的所有行。所以,这是最后一列的所有行。你可以看到最后一列是subject。好的。所以,这是我的subject列。
您可以在此处看到主题列。是的。所以让我把它写下来。所以这是最后一行,这里获取最后一列。好的,您也可以添加和修改列。所以现在我要做的是,让我再次向您展示数据框。所以这是我的数据框。我将通过将分数加倍来在此处添加另一列。好的,我们来看看。所以我已经获取了我的分数列,并将其乘以二,然后将值保存在另一个名为列中。现在由于这个列名不存在,它将被创建。所以您可以看到新的列名是双倍分数,它基本上是原始分数的两倍。您还可以使用一些 lambda 函数和 apply 函数来更新值。所以,例如,假设我想给所有学生加五分。好的。所以我为每个学生在原始分数上增加了五分。这就是这个 lambda 函数的作用。所以 x 的值是从分数列获取的,因为您正在将该 lambda 函数应用于分数列,并且 x 的每个值都将加五,然后将结果值替换回分数列。您还可以重命名列。所以现在既然我已经更新了我的分数,最好将分数列更新为更新的分数。所以现在您可以看到您的分数列不再是分数了。它是更新的分数。嗯,假设您现在认为这个双倍分数列不再需要了。您想删除它或删除它。那么我该如何删除呢?所以您可以使用 drop 方法。好的。所以 drop 方法实际上可以用来删除行和列。好的。所以这是您想要删除的标签列表,无论是行标签还是列标签。所以如果您想删除多个列,那么这将是多个列标签的列表。所以这些是我的标签。好的,这些是我的标签。Axis 等于一表示删除列,Axis 等于零表示删除行。所以本质上,您提供的任何标签列表,如果将 axis 设置为零(这是默认值),Python 都会认为这些是行的标签。所以如果您不提供 axis,它将默认为零,在这种情况下,它将开始删除行。in place 基本上意味着您想永久删除行或列,这意味着 in place 等于 true。所以您可以将其设置为 false,如果您想查看是否删除了正确的行或正确的列。无论如何,in place 选项默认为 false。所以您必须明确将其设置为 true,否则它不会被永久删除。它将从视图中删除,但不会从实际数据框中删除。好的。所以请确保如果您想永久删除它,请将其设置为 in place 等于 true。现在让我们看看如何索引一些特定的值。所以现在如果您看到,我想获取姓名列中的值以及第一个索引。好的。所以这将给我整个姓名列,现在我正在获取索引零。所以那个索引零给了我 RF patail。这正是我在这里得到的。所以您也可以切片我们的数据框。所以这是获取前两行。您实际上可以使用我之前教过的 iO 方法,或者您可以直接给出行标签的索引。您也可以重置您的索引。好的。所以假设您的原始数据框的索引是 0 1 2 3 4 5 6 7 8。这些是您的索引。您如何知道这些是索引?嗯,您可以检查 df.index。所以您的索引从零开始,到八结束。所以零到八,实际上它会以一的步长结束于七。如果您想知道存在哪些列,列名,那么 df.columns。所以这些是您的数据集中存在的列名。好的。所以这些是列名,这些是行名,基本上是标签。所以您想为行标签设置一个新名称。所以我想让这个名为列本身被设置为新索引。我想将其设置为新索引。所以这正是我将要通过此代码做的。所以现在您可以看到这个 DF 的名称。是的。所以索引不再是零到八,它之前显示的是,现在索引值是学生的实际姓名。所以这些是我的行索引。好的。所以这是一个数据框,它有正确的行和列标签。所以这些是我的列标签,这些是我的行标签。现在索引仍然是零到第一个列的索引现在是零一二三。第一行的索引仍然是零,一直到七。好的,您可以检查一下。所以无论标签是什么,索引总是从零开始。所以之前我们创建这个数据框时,行标签和索引是相同的,但现在我更改了我的行标签。索引不能更改。索引将始终是数字自动递增的。好的。所以我们也可以进行排序。所以让我根据更新的分数对整个数据框进行排序。所以默认情况下它将按升序排列。您知道什么?所以您可以按 shift tab tab,它会显示 ascending 为 true。所以默认情况下它将按升序排列。好的。所以如果您想按降序排列,那么您必须将 ascending 设置为 false。好的。所以现在它是降序排列的。96、93、86 一直到 69。所以这基本上是降序排列的。您还可以根据两列对值进行排序。所以当年龄值相等时,排序将根据更新的分数进行。所以如果您再次查看这里,这是默认的升序。所以这里的年龄值是相同的。所以排序将根据更新的分数进行。好的。所以当年龄值相同时,排序将根据分数进行。所以这是两级排序。第一级是年龄。无论如何,年龄将严格按升序排列。好的。当年龄值相同时,下一级排序将根据更新的分数进行。您也可以对索引进行排序。所以这很有趣。到目前为止,索引还没有排序。好的。现在我甚至对我的索引进行了排序。您可以看到这次是按字母顺序。A 到 S。您也可以重置索引。所以,假设您想找回您的姓名列。好的。所以您找回了您的姓名列。好的。in place 等于 true 意味着索引的重置是永久完成的。所以您的数据框再次永久更改了。它已经恢复到原始状态。现在这次我将在数据框中创建几个 nan 值或缺失值。所以一些值,看第四行,基本上是第五行,索引四。所以这是它将进行更改的行,而 -1 表示最后一行。现在列 0 1 2。所以本质上,这里将被替换为 null 值,也称为 nan。Nan 本质上不是一个数字,而是一个 null 值。所以这两个将替换这两个位置。好的,我们来看看。完美。所以这里有一个 nan,这里有另一个 nan。好的,您可能还注意到另一件事是原始数据框的年龄值是整数。这里的数据类型是整数。一旦我们有了这些缺失的 nan 值,数据类型就改变了。您可以看到小数点出现了。所以这不再是整数了。它实际上是浮点数据类型。好的,这是浮点数据类型。所以您可以通过使用 info 来验证这一点。所以您的年龄不再是整数。它是 64 位精度的浮点数。好的。所以您想知道有多少缺失值。所以这些是存在缺失值的位置,用 true 标记。所以 true 表示这些位置是缺失值。所以按每列计算缺失值的数量。所以姓名列没有任何缺失值。性别列也没有任何缺失值。年龄列有两个缺失值,而其他两列没有任何缺失值。对吧?所以按列计算有多少缺失值,您可以使用此代码来获取。所以现在您想用该列的平均值填充缺失值。比如,现在缺失值存在于年龄列中。所以您可以取平均年龄并填充缺失值。所以 fill na 函数填充 nan 值,这就是这个函数的作用,填充 nan 值。好的,fill na 是填充该列中的 nan 值。所以再次,默认情况下它是 false。所以您必须将其设置为 true,以便填充永久发生或替换原始列,任选其一。所以填充后替换原始列是一种方式,或者您可以使用 in place 选项。所以现在您可以看到这个 23.5,这个 23.5 是由于 fill na 函数而出现的。以前这些是 nan。所以您可以检查 info,如果您愿意,可以将其转换回整数格式。所以您会丢失一些精度。所以这些小数点将被忽略。好的。或者四舍五入到最接近的整数。所以我已经将其类型转换回整数。所以这取决于您的用例。您可能想这样做。所以这里使用的函数是 as type。As type 将列的数据类型更改为指定的数据类型。所以我正在将其类型转换回整数。所以您可以将其类型转换为 8 位、16 位或 32 位精度的整数。所以根据您的用例。好的。所以我正在创建一个副本的数据框后创建一些更多的缺失值。所以我正在创建一个副本,然后从该副本中删除一些更多的值。所以这次在更新的分数中创建一些更多的缺失值。您可以看到这是其中一个,这是其中一个。嗯,您还可以做的另一件事是,而不是填充缺失值,您可能想删除包含缺失值的行。所以,假设我想删除这两行包含缺失值。所以可以通过使用 drop NA 函数来完成。所以 drop NA 函数会删除缺失值,而不是用您指定的平均值或中值来填充它。所以默认情况下 axis 是零,这意味着整个行将被删除。好的,任何包含单个缺失值的行都将被删除。好的,any 意味着任何包含缺失值的单行都将被删除。所以如果您想删除列,请确保将 axis 设置为一。所以让我删除一下,您可以看到第四行和第七行被删除了。是的,第四行和第七行现在不见了。很高兴我们创建了一个副本。所以我的原始数据框仍然是相同的,未更改。如果您的数据框中有重复项怎么办?所以我在这里创建了一个简单的包含重复项的数据框。所以整个记录被复制了两次。您可以看到。所以我想删除重复项。所以您可以使用 drop duplicates 函数。所以默认情况下,它将再次删除行,并且默认情况下,in place 选项设置为 false。所以您也可以将其设置为 in place 等于 true,或者将其类型转换回原始数据框。所以删除后替换您的 df2。所以这是另一个选项,或者您使用 in place 等于 true,任选其一。所以我删除了我的重复行,您还可以对字符串进行一些操作。所以,例如,这里的科目名称我想将它们转换为小写。所以我正在将科目值类型转换为字符串,然后将该字符串转换为小写,然后替换原始列。所以将字符串值转换为小写后,我将替换我的原始列。所以这就是我在这里得到的结果。所以科目现在变成小写了。所以所有这些操作都可以根据您的用例进行。现在让我们看看如何合并和连接数据框。我正在创建几个虚拟数据框 DF1 和 DF2。我有两个名字 A 和 B,分数分别为 90 80 和 1817。在另一个中,我有这两个学生 A 和 C 的年龄,分别为 17 和 18。所以我可以进行合并操作。所以这是我的数据框在左侧,数据框在右侧。On on 将使用一个键。On on 将使用一个键。所以您可以指定要用作键的列。所以这是键。如何?所以如果您熟悉 SQL,您可能已经知道内连接、外连接、左连接和右连接。如果您不熟悉,您可以去我们的网站 analyticsia.com 阅读有关这些连接类型的信息。有很多博客解释了 SQL 连接的概念。好的。所以这里我使用的是内连接,它将匹配两个数据框中的键。所以这里的键是 AB,这里的键是 AC。所以哪个键在两者中都通用 A。这就是为什么我只在这里得到 A。所以两者中通用的键将出现。这就是内连接的含义。好的。外连接将包含左侧和右侧数据框中的键。所以我会得到 A、B 以及 C。是的。所以外连接将为您提供所有三个。如果您注意到这里,对于 B,我没有年龄值,对于 C,我没有分数。好的,因为在您的分数数据框中没有 C,在您的年龄数据框中没有 B。好的,这就是为什么 C 的分数有缺失值,B 的年龄有缺失值。对吧?A 同时存在于两个数据框中。所以分数和年龄都相应更新了。您还可以简单地将数据框一个接一个地连接起来。好的。所以在这个例子中,我创建了另一个数据框 DF3,它来自 DF1。这是我的 DF1,这是简单的 F3。所以连接意味着数据框将被连接在一起。为什么一个接一个?因为默认情况下 axis 再次为零。如果您将 axis 改为一,那么它们将被并排连接。好的,请记住这一点。所以如果您想要这种连接,您必须确保 axis 设置为一。所以 x 等于零将进行垂直连接。Axis 等于一将进行列连接,即水平连接。所以您可以看到默认情况下 axis 设置为零,这就是为什么它被垂直连接。您还可以进行分组和数据透视表。所以让我们快速进行分组。所以我在这个例子中按科目对所有数据框列或值进行分组。比如,所以按科目,我想得到更新分数的平均值。这就是这段代码的意思。所以您能给我按科目计算的更新分数平均值吗?您也可以在这里使用 sum 函数。所以获取平均分数。好的。所以这是正确的。所以类似地,您可以转到 describe 函数,其中不仅可以看到平均值,还可以看到其他统计数据。您可以在这里看到。所以这个 96、85、78 已经在 main 列中。但同时您还拥有最小值和最大值。所以按科目计算的最小值和最大值 96、96,这是一个单一值。这就是为什么标准差不是数字。所以生成式 AI 在整个数据框中只出现一次,这就是为什么无法计算标准差。所以对于 Python,标准差是 7.2,对于统计学是 7.14。Python 的最低分数是 79,最高是 93,统计学的最低分数是 69,最高是 86。似乎统计学这门课有点难。好的。所以类似地,您可以创建数据透视表。这也很像列联表。好的。所以这里您也可以设置哪个列将作为索引,哪个列将作为值。所以这里我有聚合函数。现在您的聚合函数可以是平均值、最小值、最大值、总和函数或其中任何一个。所以或中值。所以您可以对这些值应用几个聚合函数。所以聚合函数总是应用于值,您可以提供索引。所以这里是索引。所以这里是索引,聚合函数应用于这里的值。所以如果您愿意,您也可以应用多个聚合函数。是的,您可以看到。所以这是平均分数和最低分数。所以可以轻松应用多个聚合函数。那么数据透视表和分组有什么区别呢?所以分组通常用于单维摘要,而数据透视表更灵活,是多维摘要的理想选择。我们来举个例子。所以这里我正在创建一个单维摘要。对于每种性别,我想得到更新分数的平均值。所以女性的更新分数平均值为 82.33,男性的平均值为 83.6。现在不仅仅是分数的平均值,比如我想得到每种性别在三个科目上的平均分数。所以这时数据透视表会是更好的选择。所以如果您看到,所以对于每种性别和每个科目,所以这是三个科目。所以科目一、科目二、科目。对于每个科目,我都有我的平均聚合函数,这里是平均值。所以这是三个科目中每个科目的平均分数,这些科目被放在了列中。您可以看到列是科目,索引在这里是行。好的。所以索引总是指行,列在列中,而聚合函数将要应用的值。好的。所以这个聚合函数总是应用于值。所以这就是您如何通过使用数据透视表创建更复杂的摘要。最后,让我们看看如何使用 apply 和 map 函数。所以,我……所以我们已经看到了 lambda 函数应用于单个列,对吧?我们已经更新了它。所以,这些是分数。所以,让我将分数减去 10 以获得原始分数,因为我已经添加了两次。所以我将分数减去 10 以获得原始分数。现在,我在这里写了一个自定义函数,我将要应用它。这里我应用了一个简单的 lambda 函数。但是,而不是应用一个简单的 lambda 函数,您也可以应用一个自定义函数。所以这是做什么的?所以我将根据分数分配等级。所以如果分数大于 85,我将返回一个等级。如果分数在 70 到 85 之间,它将是 B 等级。如果分数小于 70,它将是 C 等级。好的。所以应用该函数到该列后,我创建了另一个名为 grade 的列。所以我也有了学生的成绩。现在您还可以映射某个列的值到其他值。所以,比如在这个例子中,我将男性映射到零,女性映射到一。这可以用于标签编码,通常用于机器学习。所以我创建了一个名为 gender new 的新列,其中零代表男性,一代表女性。这是怎么做到的?通过简单的映射器。所以您的映射器是一个字典,其中原始值成为键,新值成为值。所以您还可以使用 pandas 来处理日期和时间。我们来看看这里。我在这里创建了一个简单的包含一些姓名和日期的 DataFrame。您可以看到这些日期实际上是字符串。我怎么知道?因为 info 中存在数据类型。所以 info 给了我一个 object 数据类型。所以我可以通过使用 datetime 函数将这些字符串转换为实际的 datetime 对象。所以我正在将字符串转换为 datetime。这就是 to datetime 函数的作用。并替换原始列。所以完成之后,您可以看到视觉上它仍然与它非常相似,但如果您在这里看到 df.info,它实际上是以 datetime 格式存在的。所以您还可以提取列的日期、月份、年份中的星期、年份中的日期、年份中的月份、季度信息。所以您可以从 datetime 列中提取所有这些信息。您也可以重置索引。所以,假设您想找回您的姓名列。好的。所以您找回了您的姓名列。好的。in place 等于 true 意味着索引的重置是永久完成的。所以您的数据框再次永久更改了。它已经恢复到原始状态。现在这次我将在数据框中创建几个 nan 值或缺失值。所以一些值,看第四行,基本上是第五行,索引四。所以这是它将进行更改的行,而 -1 表示最后一行。现在列 0 1 2。所以本质上,这里将被替换为 null 值,也称为 nan。Nan 本质上不是一个数字,而是一个 null 值。所以这两个将替换这两个位置。好的,我们来看看。完美。所以这里有一个 nan,这里有另一个 nan。好的,您可能还注意到另一件事是原始数据框的年龄值是整数。这里的数据类型是整数。一旦我们有了这些缺失的 nan 值,数据类型就改变了。您可以看到小数点出现了。所以这不再是整数了。它实际上是浮点数据类型。好的,这是浮点数据类型。所以您可以通过使用 info 来验证这一点。所以您的年龄不再是整数。它是 64 位精度的浮点数。好的。所以您想知道有多少缺失值。所以这些是存在缺失值的位置。用 true 标记。所以 true 表示这些位置是缺失值。所以按每列计算缺失值的数量。所以姓名列没有任何缺失值。性别列也没有任何缺失值。年龄列有两个缺失值,而其他两列没有任何缺失值。对吧?所以按列计算有多少缺失值,您可以使用此代码来获取。所以现在您想用该列的平均值填充缺失值。比如,现在缺失值存在于年龄列中。所以您可以取平均年龄并填充缺失值。所以 fill na 函数填充 nan 值,这就是这个函数的作用,填充 nan 值。好的,fill na 是填充该列中的 nan 值。所以再次,默认情况下它是 false。所以您必须将其设置为 true,以便填充永久发生或替换原始列,任选其一。所以填充后替换原始列是一种方式,或者您可以使用 in place 选项。所以现在您可以看到这个 23.5,这个 23.5 是由于 fill na 函数而出现的。以前这些是 nan。所以您可以检查 info,如果您愿意,可以将其转换回整数格式。所以您会丢失一些精度。所以这些小数点将被忽略。好的。或者四舍五入到最接近的整数。所以我已经将其类型转换回整数。所以这取决于您的用例。您可能想这样做。所以这里使用的函数是 as type。As type 将列的数据类型更改为指定的数据类型。所以我正在将其类型转换回整数。所以您可以将其类型转换为 8 位、16 位或 32 位精度的整数。所以根据您的用例。好的。所以我正在创建一个副本的数据框后创建一些更多的缺失值。所以我正在创建一个副本,然后从该副本中删除一些更多的值。所以这次在更新的分数中创建一些更多的缺失值。您可以看到这是其中一个,这是其中一个。嗯,您还可以做的另一件事是,而不是填充缺失值,您可能想删除包含缺失值的行。所以,假设我想删除这两行包含缺失值。所以可以通过使用 drop NA 函数来完成。所以 drop NA 函数会删除缺失值,而不是用您指定的平均值或中值来填充它。所以默认情况下 axis 是零,这意味着整个行将被删除。好的,任何包含单个缺失值的行都将被删除。好的,any 意味着任何包含缺失值的单行都将被删除。所以如果您想删除列,请确保将 axis 设置为一。所以让我删除一下,您可以看到第四行和第七行被删除了。是的,第四行和第七行不见了。很高兴我们创建了一个副本。所以我的原始数据框仍然是相同的,未更改。如果您的数据框中有重复项怎么办?所以我在这里创建了一个简单的包含重复项的数据框。所以整个记录被复制了两次。您可以看到。所以我想删除重复项。所以您可以使用 drop duplicates 函数。所以默认情况下,它将再次删除行,并且默认情况下,in place 选项设置为 false。所以您也可以将其设置为 in place 等于 true,或者将其类型转换回原始数据框。所以删除后替换您的 df2。所以这是另一个选项,或者您使用 in place 等于 true,任选其一。所以我删除了我的重复行,您还可以对字符串进行一些操作。所以,例如,这里的科目名称我想将它们转换为小写。所以我正在将科目值类型转换为字符串,然后将该字符串转换为小写,然后替换原始列。所以将字符串值转换为小写后,我将替换我的原始列。所以这就是我在这里得到的结果。所以科目现在变成小写了。所以所有这些操作都可以根据您的用例进行。现在让我们看看如何合并和连接数据框。我正在创建几个虚拟数据框。DF1 和 DF2。我有两个名字 A 和 B,分数分别为 90 80 和 1817。在另一个中,我有这两个学生 A 和 C 的年龄,分别为 17 和 18。所以我可以进行合并操作。所以这是我的数据框在左侧,数据框在右侧。On on 将使用一个键。On on 将使用一个键。所以您可以指定要用作键的列。所以这是键。如何?所以如果您熟悉 SQL,您可能已经知道内连接、外连接、左连接和右连接。如果您不熟悉,您可以去我们的网站 analytics.com 阅读有关这些连接类型的信息。有很多博客解释了 SQL 连接的概念。好的。所以这里我使用的是内连接,它将匹配两个数据框中的键。所以这里的键是 AB,这里的键是 AC。所以哪个键在两者中都通用 A。这就是为什么我只在这里得到 A。所以两者中通用的键将出现。这就是内连接的含义。好的。外连接将包含左侧和右侧数据框中的键。所以我会得到 A、B 以及 C。是的。所以外连接将为您提供所有三个。如果您注意到这里,对于 B,我没有年龄值,对于 C,我没有分数。好的,因为在您的分数数据框中没有 C,在您的年龄数据框中没有 B。好的,这就是为什么 C 的分数有缺失值,B 的年龄有缺失值。对吧?A 同时存在于两个数据框中。所以分数和年龄都相应更新了。您还可以简单地将数据框一个接一个地连接起来。好的。所以在这个例子中,我创建了另一个数据框 DF3,它来自 DF1。这是我的 DF1,这是简单的 F3。所以连接意味着数据框将被连接在一起。为什么一个接一个?因为默认情况下 axis 再次为零。如果您将 axis 改为一,那么它们将被并排连接。好的,请记住这一点。所以如果您想要这种连接,您必须确保 axis 设置为一。所以 x 等于零将进行垂直连接。Axis 等于一将进行列连接,即水平连接。所以您可以看到默认情况下 axis 设置为零,这就是为什么它被垂直连接。您还可以进行分组和数据透视表。所以让我们快速进行分组。所以我在这个例子中按科目对所有数据框列或值进行分组。比如,所以按科目,我想得到更新分数的平均值。这就是这段代码的意思。所以您能给我按科目计算的更新分数平均值吗?您也可以在这里使用 sum 函数。所以获取平均分数。好的。所以这是正确的。所以类似地,您可以转到 describe 函数,其中不仅可以看到平均值,还可以看到其他统计数据。您可以在这里看到。所以这个 96、85、78 已经在 main 列中。但同时您还拥有最小值和最大值。所以按科目计算的最小值和最大值 96、96,这是一个单一值。这就是为什么标准差不是数字。所以生成式 AI 在整个数据框中只出现一次,这就是为什么无法计算标准差。所以对于 Python,标准差是 7.2,对于统计学是 7.14。Python 的最低分数是 79,最高是 93,统计学的最低分数是 69,最高是 86。似乎统计学这门课有点难。好的。所以类似地,您可以创建数据透视表。这也很像列联表。好的。所以这里您也可以设置哪个列将作为索引,哪个列将作为值。所以这里我有聚合函数。现在您的聚合函数可以是平均值、最小值、最大值、总和函数或其中任何一个。所以或中值。所以您可以对这些值应用几个聚合函数。所以聚合函数总是应用于值,您可以提供索引。所以这里是索引。所以这里是索引,聚合函数应用于这里的值。所以如果您愿意,您也可以应用多个聚合函数。是的,您可以看到。所以这是平均分数和最低分数。所以可以轻松应用多个聚合函数。那么数据透视表和分组有什么区别呢?所以分组通常用于单维摘要,而数据透视表更灵活,是多维摘要的理想选择。我们来举个例子。所以这里我正在创建一个单维摘要。对于每种性别,我想得到更新分数的平均值。所以女性的更新分数平均值为 82.33,男性的平均值为 83.6。现在不仅仅是分数的平均值,比如我想得到每种性别在三个科目上的平均分数。所以这时数据透视表会是更好的选择。所以如果您看到,所以对于每种性别和每个科目,所以这是三个科目。所以科目一、科目二、科目。对于每个科目,我都有我的平均聚合函数,这里是平均值。所以这是三个科目中每个科目的平均分数,这些科目被放在了列中。您可以看到列是科目,索引在这里是行。好的。所以索引总是指行,列在列中,而聚合函数将要应用的值。好的。所以这个聚合函数总是应用于值。所以这就是您如何通过使用数据透视表创建更复杂的摘要。最后,让我们看看如何使用 apply 和 map 函数。所以,我……所以我们已经看到了 lambda 函数应用于单个列,对吧?我们已经更新了它。所以,这些是分数。所以,让我将分数减去 10 以获得原始分数,因为我已经添加了两次。所以我将分数减去 10 以获得原始分数。现在,我在这里写了一个自定义函数,我将要应用它。这里我应用了一个简单的 lambda 函数。但是,而不是应用一个简单的 lambda 函数,您也可以应用一个自定义函数。所以这是做什么的?所以我将根据分数分配等级。所以如果分数大于 85,我将返回一个等级。如果分数在 70 到 85 之间,它将是 B 等级。如果分数小于 70,它将是 C 等级。好的。所以应用该函数到该列后,我创建了另一个名为 grade 的列。所以我也有了学生的成绩。现在您还可以映射某个列的值到其他值。所以,比如在这个例子中,我将男性映射到零,女性映射到一。这可以用于标签编码,通常用于机器学习。所以我创建了一个名为 gender new 的新列,其中零代表男性,一代表女性。这是怎么做到的?通过简单的映射器。所以您的映射器是一个字典,其中原始值成为键,新值成为值。所以您还可以使用 pandas 来处理日期和时间。我们来看看这里。我在这里创建了一个简单的包含一些姓名和日期的 DataFrame。您可以看到这些日期实际上是字符串。我怎么知道?因为 info 中存在数据类型。所以 info 给了我一个 object 数据类型。所以我可以通过使用 datetime 函数将这些字符串转换为实际的 datetime 对象。所以我正在将字符串转换为 datetime。这就是 to datetime 函数的作用。并替换原始列。所以完成之后,您可以看到视觉上它仍然与它非常相似,但如果您在这里看到 df.info,它实际上是以 datetime 格式存在的。所以您还可以提取列的日期、月份、年份中的星期、年份中的日期、年份中的月份、季度信息。所以您可以从 datetime 列中提取所有这些信息。您也可以重置索引。所以,假设您想找回您的姓名列。好的。所以您找回了您的姓名列。好的。in place 等于 true 意味着索引的重置是永久完成的。所以您的数据框再次永久更改了。它已经恢复到原始状态。现在这次我将在数据框中创建几个 nan 值或缺失值。所以一些值,看第四行,基本上是第五行,索引四。所以这是它将进行更改的行,而 -1 表示最后一行。现在列 0 1 2。所以本质上,这里将被替换为 null 值,也称为 nan。Nan 本质上不是一个数字,而是一个 null 值。所以这两个将替换这两个位置。好的,我们来看看。完美。所以这里有一个 nan,这里有另一个 nan。好的,您可能还注意到另一件事是原始数据框的年龄值是整数。这里的数据类型是整数。一旦我们有了这些缺失的 nan 值,数据类型就改变了。您可以看到小数点出现了。所以这不再是整数了。它实际上是浮点数据类型。好的,这是浮点数据类型。所以您可以通过使用 info 来验证这一点。所以您的年龄不再是整数。它是 64 位精度的浮点数。好的。所以您想知道有多少缺失值。所以这些是存在缺失值的位置。用 true 标记。所以 true 表示这些位置是缺失值。所以按每列计算缺失值的数量。所以姓名列没有任何缺失值。性别列也没有任何缺失值。年龄列有两个缺失值,而其他两列没有任何缺失值。对吧?所以按列计算有多少缺失值,您可以使用此代码来获取。所以现在您想用该列的平均值填充缺失值。比如,现在缺失值存在于年龄列中。所以您可以取平均年龄并填充缺失值。所以 fill na 函数填充 nan 值,这就是这个函数的作用,填充 nan 值。好的,fill na 是填充该列中的 nan 值。所以再次,默认情况下它是 false。所以您必须将其设置为 true,以便填充永久发生或替换原始列,任选其一。所以填充后替换原始列是一种方式,或者您可以使用 in place 选项。所以现在您可以看到这个 23.5,这个 23.5 是由于 fill na 函数而出现的。以前这些是 nan。所以您可以检查 info,如果您愿意,可以将其转换回整数格式。所以您会丢失一些精度。所以这些小数点将被忽略。好的。或者四舍五入到最接近的整数。所以我已经将其类型转换回整数。所以这取决于您的用例。您可能想这样做。所以这里使用的函数是 as type。As type 将列的数据类型更改为指定的数据类型。所以我正在将其类型转换回整数。所以您可以将其类型转换为 8 位、16 位或 32 位精度的整数。所以根据您的用例。好的。所以我正在创建一个副本的数据框后创建一些更多的缺失值。所以我正在创建一个副本,然后从该副本中删除一些更多的值。所以这次在更新的分数中创建一些更多的缺失值。您可以看到这是其中一个,这是其中一个。嗯,您还可以做的另一件事是,而不是填充缺失值,您可能想删除包含缺失值的行。所以,假设我想删除这两行包含缺失值。所以可以通过使用 drop NA 函数来完成。所以 drop NA 函数会删除缺失值,而不是用您指定的平均值或中值来填充它。所以默认情况下 axis 是零,这意味着整个行将被删除。好的,任何包含单个缺失值的行都将被删除。好的,any 意味着任何包含缺失值的单行都将被删除。所以如果您想删除列,请确保将 axis 设置为一。所以让我删除一下,您可以看到第四行和第七行被删除了。是的,第四行和第七行不见了。很高兴我们创建了一个副本。所以我的原始数据框仍然是相同的,未更改。如果您的数据框中有重复项怎么办?所以我在这里创建了一个简单的包含重复项的数据框。所以整个记录被复制了两次。您可以看到。所以我想删除重复项。所以您可以使用 drop duplicates 函数。所以默认情况下,它将再次删除行,并且默认情况下,in place 选项设置为 false。所以您也可以将其设置为 in place 等于 true,或者将其类型转换回原始数据框。所以删除后替换您的 df2。所以这是另一个选项,或者您使用 in place 等于 true,任选其一。所以我删除了我的重复行,您还可以对字符串进行一些操作。所以,例如,这里的科目名称我想将它们转换为小写。所以我正在将科目值类型转换为字符串,然后将该字符串转换为小写,然后替换原始列。所以将字符串值转换为小写后,我将替换我的原始列。所以这就是我在这里得到的结果。所以科目现在变成小写了。所以所有这些操作都可以根据您的用例进行。现在让我们看看如何合并和连接数据框。我正在创建几个虚拟数据框。DF1 和 DF2。我有两个名字 A 和 B,分数分别为 90 80 和 1817。在另一个中,我有这两个学生 A 和 C 的年龄,分别为 17 和 18。所以我可以进行合并操作。所以这是我的数据框在左侧,数据框在右侧。On on 将使用一个键。On on 将使用一个键。所以您可以指定要用作键的列。所以这是键。如何?所以如果您熟悉 SQL,您可能已经知道内连接、外连接、左连接和右连接。如果您不熟悉,您可以去我们的网站 analytics.com 阅读有关这些连接类型的信息。有很多博客解释了 SQL 连接的概念。好的。所以这里我使用的是内连接,它将匹配两个数据框中的键。所以这里的键是 AB,这里的键是 AC。所以哪个键在两者中都通用 A。这就是为什么我只在这里得到 A。所以两者中通用的键将出现。这就是内连接的含义。好的。外连接将包含左侧和右侧数据框中的键。所以我会得到 A、B 以及 C。是的。所以外连接将为您提供所有三个。如果您注意到这里,对于 B,我没有年龄值,对于 C,我没有分数。好的,因为在您的分数数据框中没有 C,在您的年龄数据框中没有 B。好的,这就是为什么 C 的分数有缺失值,B 的年龄有缺失值。对吧?A 同时存在于两个数据框中。所以分数和年龄都相应更新了。您还可以简单地将数据框一个接一个地连接起来。好的。所以在这个例子中,我创建了另一个数据框 DF3,它来自 DF1。这是我的 DF1,这是简单的 F3。所以连接意味着数据框将被连接在一起。为什么一个接一个?因为默认情况下 axis 再次为零。如果您将 axis 改为一,那么它们将被并排连接。好的,请记住这一点。所以如果您想要这种连接,您必须确保 axis 设置为一。所以 x 等于零将进行垂直连接。Axis 等于一将进行列连接,即水平连接。所以您可以看到默认情况下 axis 设置为零,这就是为什么它被垂直连接。您还可以进行分组和数据透视表。所以让我们快速进行分组。所以我在这个例子中按科目对所有数据框列或值进行分组。比如,所以按科目,我想得到更新分数的平均值。这就是这段代码的意思。所以您能给我按科目计算的更新分数平均值吗?您也可以在这里使用 sum 函数。所以获取平均分数。好的。所以这是正确的。所以类似地,您可以转到 describe 函数,其中不仅可以看到平均值,还可以看到其他统计数据。您可以在这里看到。所以这个 96、85、78 已经在 main 列中。但同时您还拥有最小值和最大值。所以按科目计算的最小值和最大值 96、96,这是一个单一值。这就是为什么标准差不是数字。所以生成式 AI 在整个数据框中只出现一次,这就是为什么无法计算标准差。所以对于 Python,标准差是 7.2,对于统计学是 7.14。Python 的最低分数是 79,最高是 93,统计学的最低分数是 69,最高是 86。似乎统计学这门课有点难。好的。所以类似地,您可以创建数据透视表。这也很像列联表。好的。所以这里您也可以设置哪个列将作为索引,哪个列将作为值。所以这里我有聚合函数。现在您的聚合函数可以是平均值、最小值、最大值、总和函数或其中任何一个。所以或中值。所以您可以对这些值应用几个聚合函数。所以聚合函数总是应用于值,您可以提供索引。所以这里是索引。所以这里是索引,聚合函数应用于这里的值。所以如果您愿意,您也可以应用多个聚合函数。是的,您可以看到。所以这是平均分数和最低分数。所以可以轻松应用多个聚合函数。那么数据透视表和分组有什么区别呢?所以分组通常用于单维摘要,而数据透视表更灵活,是多维摘要的理想选择。我们来举个例子。所以这里我正在创建一个单维摘要。对于每种性别,我想得到更新分数的平均值。所以女性的更新分数平均值为 82.33,男性的平均值为 83.6。现在不仅仅是分数的平均值,比如我想得到每种性别在三个科目上的平均分数。所以这时数据透视表会是更好的选择。所以如果您看到,所以对于每种性别和每个科目,所以这是三个科目。所以科目一、科目二、科目。对于每个科目,我都有我的平均聚合函数,这里是平均值。所以这是三个科目中每个科目的平均分数,这些科目被放在了列中。您可以看到列是科目,索引在这里是行。好的。所以索引总是指行,列在列中,而聚合函数将要应用的值。好的。所以这个聚合函数总是应用于值。所以这就是您如何通过使用数据透视表创建更复杂的摘要。最后,让我们看看如何使用 apply 和 map 函数。所以,我……所以我们已经看到了 lambda 函数应用于单个列,对吧?我们已经更新了它。所以,这些是分数。所以,让我将分数减去 10 以获得原始分数,因为我已经添加了两次。所以我将分数减去 10 以获得原始分数。现在,我在这里写了一个自定义函数,我将要应用它。这里我应用了一个简单的 lambda 函数。但是,而不是应用一个简单的 lambda 函数,您也可以应用一个自定义函数。所以这是做什么的?所以我将根据分数分配等级。所以如果分数大于 85,我将返回一个等级。如果分数在 70 到 85 之间,它将是 B 等级。如果分数小于 70,它将是 C 等级。好的。所以应用该函数到该列后,我创建了另一个名为 grade 的列。所以我也有了学生的成绩。现在您还可以映射某个列的值到其他值。所以,比如在这个例子中,我将男性映射到零,女性映射到一。这可以用于标签编码,通常用于机器学习。所以我创建了一个名为 gender new 的新列,其中零代表男性,一代表女性。这是怎么做到的?通过简单的映射器。所以您的映射器是一个字典,其中原始值成为键,新值成为值。所以您还可以使用 pandas 来处理日期和时间。我们来看看这里。我在这里创建了一个简单的包含一些姓名和日期的 DataFrame。您可以看到这些日期实际上是字符串。我怎么知道?因为 info 中存在数据类型。所以 info 给了我一个 object 数据类型。所以我可以通过使用 datetime 函数将这些字符串转换为实际的 datetime 对象。所以我正在将字符串转换为 datetime。这就是 to datetime 函数的作用。并替换原始列。所以完成之后,您可以看到视觉上它仍然与它非常相似,但如果您在这里看到 df.info,它实际上是以 datetime 格式存在的。所以您还可以提取列的日期、月份、年份中的星期、年份中的日期、年份中的月份、季度信息。所以您可以从 datetime 列中提取所有这些信息。现在,这就是本视频关于使用 pandas 进行数据分析的广泛编码教程的全部内容。今天我们将深入探讨数据库和 SQL 基础知识。理解数据库以及如何使用 SQL 是任何从事数据工作的人的一项基本技能,尤其是在人工智能和机器学习领域。在本模块中,我们将了解数据库、它们的类型,SQL 的作用,以及这些技能如何融入 AI 工作流程。让我们开始吧。在本视频中,我们将涵盖几个关键主题。我们将首先定义什么是数据库,并探索不同类型的数据库。我们将讨论为什么数据库至关重要,尤其是在 AI 的背景下。然后我们将介绍 SQL,结构化查询语言,它是与关系数据库交互的标准语言。我们将介绍基本的 SQL 命令。最后,我们将了解数据库如何连接到 AI 代理。数据库本质上是有组织的数据集合。将其视为一个数字文件系统,允许您高效地存储、检索和管理数据。数据库当然由数据组成,但它们也依赖于硬件(如服务器)、软件(数据库管理系统)以及与之交互的用户。这种组织允许快速访问和操作大量信息,这在包括 AI 在内的许多应用中至关重要。想想您每天使用的所有应用程序和服务,如社交媒体、银行、购物等。所有这些服务都依赖数据库来存储有关用户、交易、产品等的海量信息。数据库主要有两种类型:关系型和非关系型。关系型数据库将数据组织成具有行和列的表,非常像电子表格,它们使用 SQL 进行数据查询和管理。例如包括 MySQL、Postgrace SQL 和 SQite。它们非常适合存储具有固定关系的数据。想想与订单关联的客户记录。非关系型数据库,通常称为 NoSQL 数据库,以文档、键值对甚至图等格式存储数据,从而允许它们更灵活的模式设计。NoSQL 数据库的例子包括 MongoDB、radius 和 Cassandra。当数据不适合表格时,或者当可扩展性至关重要时,例如在社交媒体应用程序中,通常会使用它们。数据库通过提供一个集中的数据存储和组织场所,在数据管理中发挥着关键作用。它们旨在处理大量数据,使它们成为满足不断增长需求的可扩展解决方案。数据库确保数据完整性,这意味着数据随着时间的推移保持准确和一致。它们还支持并发,允许多个用户同时访问和修改数据而不会发生冲突。对我们来说最重要的是,数据库是 AI 的基础,因为数据是驱动 AI 算法的燃料。现在,让我们谈谈 SQL,结构化查询语言。SQL 是用于与关系数据库通信的标准语言。它用于创建表、插入和检索数据以及执行更新和删除。如果您将数据库视为图书馆,那么 SQL 就是图书管理员,帮助您找到所需的书籍、更新信息,甚至将新书添加到书架上。理解 SQL 可以让您有效地与数据库交互。检索您应用程序所需的精确信息。让我们看一些基本的 SQL 命令。CREATE TABLE 命令用于在数据库中创建新表并定义该表的结构,包括其列和数据类型。INSERT INTO 允许我们将新记录或行添加到表中。UPDATE 允许我们修改现有数据。DELETE 允许我们从表中删除数据。而 SELECT 命令用于从数据库检索数据。它是最常用的命令之一。数据库在 AI 领域至关重要,原因有几个。它们为训练 AI 模型通常需要的大量数据集提供了高效的存储解决方案。数据库使数据访问和预处理更加容易,这是任何 AI 项目的关键步骤。它们提供可靠且一致的数据源,确保模型在准确的信息上进行训练。对于需要实时数据的 AI 代理来说,数据库可以提供最新的信息,从而实现更动态和响应迅速的 AI 系统。要利用 AI 应用程序中的数据库,我们需要将它们连接到 Python 等编程语言。这是通过使用允许我们执行 SQL 查询和操作代码中的数据的库和工具来完成的。Python 提供了几个库,如用于 SQLite 数据库的 SQLite 3、用于 MySQL 的 PI MySQL 和用于 Postgrace SQL 的 Psychopg2。ORM 框架(如 SQL Alchemy)可以通过允许我们将数据库视为普通 Python 对象来简化数据库交互。连接后,我们可以提取数据、预处理数据,并将其馈送到 AI 算法进行处理和决策。我们已经在之前的模块中讨论了将 Python 连接到 SQL 数据库。但让我们简要回顾一下。使用 Python,我们可以使用 SQLite 3、Psychopg2 和 SQL Alchemy 等库连接到 SQLite 和 Post SQL 等数据库。这样做的优点是它提供了高效的数据管理,允许 Python 脚本读取、更新和存储结构化数据。此功能对于构建强大的数据驱动应用程序至关重要,而这些应用程序是 AI 和机器学习项目的支柱。在本视频中,我们将探讨如何将 Python 应用程序连接到 MySQL 和 Postgress SQL 等 SQL 数据库。我们将讨论其优势和用例,尤其是在 AI 代理和生成式 AI 应用程序的背景下,并提供代码示例来说明这些概念。在本课程结束时,您将对如何将数据库集成到您的 Python 项目中有一个基本的了解,从而实现更动态和数据驱动的 AI 解决方案。本视频的议程包括了解将 Python 连接到 SQL 数据库的原因和好处。我们将深入研究连接到 MySQL 和 Postgress SQL 数据库的实际代码示例。我们还将学习如何直接从 Python 和 pandas 执行 SQL 查询,并讨论如何处理导入到 Python 中的数据。为什么将 Python 连接到 SQL 数据库?将 Python 连接到 SQL 数据库提供了许多优势。数据库旨在高效地存储和检索大量数据,这对于需要访问大量数据集的 AI 应用程序至关重要。它们提供可扩展性和高性能,确保您的应用程序能够应对增长。实时数据访问允许 AI 代理根据最新信息做出决策。此外,将数据库与 Python 集成可以实现无缝的数据预处理,这对于训练准确的 AI 模型至关重要。将 Python 连接到 SQL 数据库的用例非常广泛。例如,需要动态数据的 AI 代理可以即时检索和处理客户信息。聊天机器人是一个很好的例子。它们需要访问最新的客户数据才能提供有用的响应。另一个用例是依赖存储数据集进行训练和推理的生成式 AI 应用程序。想象一下为流媒体平台开发一个推荐系统。用户偏好和内容元数据的数据必须从中央存储库(将是数据库)中提取。此外,日志记录和监控在维护系统方面起着重要作用。数据库用于存储用户交互日志,这些日志可以进行分析以改进性能和用户体验。连接 Python 到 SQL 数据库的工具。有几种工具和库可用于将 Python 连接到 SQL 数据库。对于 MySQL,流行的 Python 库包括 MySQL connector Python 和 PI MySQL 库。对于 Postgress SQL,有 PsychoPG2 和 PG8000 库。对于那些喜欢抽象掉原始 SQL 代码的 ORM 框架的人来说,SQL Alchemy 是一个强大的选项,它支持多种数据库。ORM 有助于使用 Python 类和方法与数据库进行交互,而不是编写原始 SQL 查询。此外,pandas 也与 SQL 函数很好地集成,例如 pandas.SQL ReadSQL query 可以轻松地将数据导入数据框,而 two_SSQL 方法允许您将数据框中的数据写入 SQL 表。另一个有趣的概念是内存数据库,SQLite 是一个很好的例子。内存数据库完全驻留在您的系统 RAM 中,从而使读写操作非常快速。但是,数据是易失的,这意味着当应用程序终止时数据就会丢失。内存数据库非常适合测试和开发,因为它们为每次测试运行提供了一个新的数据库状态。它们也非常适合需要快速数据访问的应用程序,例如缓存或管理不需要长期持久性的会话数据。在 Python 中创建内存 SQLite 数据库非常简单。通过将 memory 传递给 SQLite 3.Connect 函数,我们告诉 SQLite 在 RAM 中创建一个临时数据库。在代码示例中,我们建立连接、创建表、插入数据、查询它,最后关闭连接。所有操作都在内存中执行,并且没有数据写入磁盘。何时使用内存数据库?内存数据库在速度至关重要的场景中非常有用,因为它们在 RAM 中运行。读写操作比基于磁盘的数据库快得多。这使它们成为需要快速处理数据的应用程序的理想选择。它们也非常适合测试和开发。使用内存数据库允许开发人员运行测试,而无需设置测试数据库环境。每次测试都可以从一个干净的开始,确保测试的隔离性和可重复性。使用内存数据库的限制。易失性。由于数据驻留在易失性内存中,因此在应用程序结束时不会保留。这意味着您不应该在需要数据持久性的应用程序中使用内存数据库。内存限制。此外,它们受限于可用的系统内存,因此不适合大型数据集。并发性。它们在处理并发连接方面也可能存在限制,这对于多线程应用程序来说可能是一个问题。在决定是否为您的项目使用内存数据库时,理解这些权衡至关重要。为了克服内存数据库的这些限制,我们有持久数据库,如 MySQL、Postgress SQL、MongoDB、Reddis、Cassandra 等。连接到 MySQL 数据库。让我们看看如何使用 MySQL connector Python 库连接到 MySQL 数据库。首先,我们
导入库。然后我们尝试使用 MySQL.Connector.connect 函数建立连接,提供必要的参数,如主机、用户、密码和数据库名称。我们将此包装在 try-except 块中,以优雅地处理任何连接错误。如果连接成功,我们将打印一条确认消息。使用 psychopg2 连接到 PostgreSQL 数据库遵循类似的模式。我们导入 psychopg2 库,然后尝试使用 psychopg2.connect 函数进行连接。同样,我们提供主机、用户、密码和数据库名称。将连接尝试包装在 try-except 块中,有助于我们捕获和处理在此过程中可能发生的任何错误。一旦我们建立了到数据库的连接,我们就可以直接从 Python 执行 SQL 查询,并将结果提取到 pandas 数据框中。这是使用 pandas 的 read_sql_query 函数完成的,该函数将 SQL 查询和数据库连接作为参数。在执行查询并将结果存储在数据框中之后,关闭数据库连接是一个好习惯。对于 MySQL 和 PostgreSQL,过程是相似的,主要区别在于用于连接的库。直接 SQL 查询的局限性。在 Python 中编写原始 SQL 查询时,需要考虑一些限制。首先,SQL 查询可能会变得复杂且难以管理,尤其是在大型项目中。编写和调试冗长复杂的 SQL 查询可能非常耗时。另一个问题是安全性。如果处理不当,原始查询容易受到 SQL 注入攻击。始终确保用户输入经过清理和参数化,以避免这些风险。最后是可维护性。随着代码应用程序的增长,在 Python 代码中维护原始 SQL 查询可能会变得麻烦。当有大量嵌入式 SQL 语句时,重构和保持代码整洁会更加困难。为了克服原始 SQL 查询的局限性,您可以使用对象关系映射 (ORM) 框架,如 SQLAlchemy 或 SQLModel。ORM 允许您使用 Python 类和对象与数据库进行交互,而不是使用原始 SQL 代码。这提供了一个抽象层,使开发更快,代码更易于维护。使用 ORM,您可以通过在 Python 中定义类来创建和修改表。这不仅提高了生产力,而且在需要时也更容易在数据库之间切换,因为相同的 Python 代码可以与不同的数据库后端一起使用。SQLAlchemy 在 Python 生态系统中享有盛誉,提供强大的功能和对各种数据库的支持。SQLModel 基于 SQLAlchemy 和 Pydantic 构建,使用现代 Python 语法和类型注解简化了模型创建。它简化了定义数据库模型的过程,并与 FastAPI 很好地集成,使其成为构建需要数据持久性和验证的 API 和 AI 应用程序的理想选择。让我们总结一下我们今天学到的内容。将 Python 连接到 SQL 数据库可以实现高效可扩展的数据处理。我们探索了像 MySQL Connector/Python 和 psychopg2 这样的库来进行数据库连接。Pandas 与 SQL 数据库无缝集成以进行数据操作,使其成为数据分析的强大工具。ORM 框架,如 SQLAlchemy 和 SQLModel,在原始 SQL 查询方面提供了优势,包括抽象、生产力和更易于维护。这些概念对于构建数据驱动的应用程序至关重要,掌握它们将使您的工作流程更加高效。大家好,欢迎回来。在本视频中,我们将探讨如何在 Python 中处理文件和数据库。在构建真实世界的数据驱动应用程序时,了解如何处理文件和数据库至关重要。我们将深入探讨 CSV 和 JSON 文件格式,如何在 Python 中与它们交互,以及如何将它们与数据库集成。让我们开始吧。本视频将涵盖以下内容。我们将从介绍 Python 中的文件处理开始,重点关注 CSV 和 JSON 文件,然后提供代码示例来说明如何读取和写入这些文件类型。那么,为什么我们需要处理文件呢?数据存储和交换是最常见的用途之一。文件,尤其是在 CSV 和 JSON 等格式中,可以轻松地在不同系统和应用程序之间存储、共享和交换数据。CSV 文件用于表格数据,而 JSON 文件广泛用于 API 之间的结构化数据交换。此外,文件通常用于数据预处理,为 AI 模型和分析准备数据。它们提供了一种易于读取的方式来记录、存储和传输我们机器学习工作流所需的信息。Python 提供了像 CSV 和 JSON 这样的内置模块,可以轻松处理 CSV 和 JSON 文件。此外,像 pandas 这样的第三方库提供了强大的数据操作功能,可以更轻松地为 AI 应用程序预处理数据。CSV 文件通常用于存储表格数据,如电子表格或简单数据库。Python 的 CSV 模块允许您使用 csv.reader 函数读取这些文件,并使用 csv.writer 函数写入它们。csv.reader 函数读取 CSV 文件的每一行并将其作为列表返回。类似地,csv.writer 函数允许您将数据行写回 CSV 格式。该模块非常适合中小型数据集以及那些希望在不需要高级数据操作的情况下处理 CSV 的用户。但是,对于大型数据集或需要高级数据操作的情况,pandas 是更好的选择。它允许您将 CSV 文件读取到数据框中,数据框是用于数据分析和预处理的强大数据结构。以下是如何使用 pandas 读取和写入 CSV 文件的示例。首先,我们导入 pandas 并使用 pd.read_csv 函数将数据从 data.csv 读取到数据框中。然后,我们可以使用 df.head 函数显示前几行。在执行一些数据操作(例如计算新的总计列)后,我们可以使用 DataFrame.to_csv 函数将数据框写入新的 CSV 文件。将 index 设置为 False 可防止 pandas 将行索引写入文件。使用 Python 读取和写入 JSON 文件。JSON 模块是 Python 标准库的一部分,并提供了读取和写入 JSON 数据的函数。JSON 对象类似于 Python 字典,使其易于处理。您可以使用 json.load 函数从文件读取 JSON 数据到 Python 字典中。反之,json.dump 函数允许您将字典写入 JSON 文件。要处理字符串格式的 JSON 数据,您可以使用 json.loads 函数和 json.dumps 函数。使用 JSON 模块处理 JSON 文件。在此示例中,我们使用 json.load 函数从 data.json 读取数据,该函数将 JSON 内容加载到 Python 字典中。然后,我们可以使用 data['employees'] 访问数据结构中的元素。修改数据(在此情况下添加新员工)后,我们使用 json.dump 将更新后的字典写回文件。index=4 参数使用缩进格式化 JSON 文件,以提高可读性。总之,使用标准库可以轻松处理 Python 中的 CSV 和 JSON 等文件,并且像 pandas 这样的工具可以增强这些功能。我希望本次会议能为您提供有关在 Python 中处理文件和数据库的宝贵见解。那么,在本编码教程中,我们将了解如何使用 Python 连接到 SQL 数据库。首先,我们将从内存数据库开始,这些数据库是使用 SQLite 包创建的,然后我们将连接到一个 MySQL 数据库和另一个 PostgreSQL 数据库,这两个数据库都托管在 AWS 服务器上,这在任何实际的企业场景中很可能是一个生产环境。那么,让我们开始吧。好的。因此,您需要安装 SQLite3 包(如果尚未安装)。您可以通过执行 pip install sqlite3 来完成此操作。我没有运行它,因为该包已安装在我的系统中。然后,如果您使用 Anaconda 或 Google Colab,pandas 很可能已安装在您的系统中。在这里,我通过连接到内存来创建一个 SQLite 数据库。此数据库将在您的 RAM(即我将在此指定的内存)中创建。然后,一旦与该数据库建立连接,我将创建一个游标对象。此游标对象将用于执行 SQL 命令。已完成。现在,我将执行一个 CREATE TABLE 查询,该查询将创建一个名为 students 的小型表。此 students 表将包含 ID、姓名、年龄以及统计学、Python、机器学习和深度学习等几个科目的分数。这些将是表中的列。表名为 students,此 students 表将在您的数据库中创建。因此,我将整个查询字符串传递给 execute,然后由游标执行。好的,让我们看看。好的,students 表已创建。现在,我将向该表中插入一些数据。好的,为此,我使用 INSERT INTO 命令。因此,INSERT INTO students,这些是列名,并且有一些我指定的条目。这些是学生的姓名、年龄,然后是统计学分数、Python 分数、机器学习分数和深度学习分数。好的。这些是相当标准的 SQL 命令。如果您熟悉,可以轻松关联。如果 SQL 对您来说有点新,我强烈建议您学习一些 SQL 的基础知识。查询字符串再次执行并已提交。执行意味着它将执行并将数据插入表中(临时),如果有任何错误,我们可以随时回滚。一旦没有错误,我就可以要求它提交。提交就像一个永久操作。所以,完美。数据已插入。现在您可以直接向您的表发出一些查询字符串。好的。我在这里传递的一个简单查询是 SELECT * FROM students。这意味着我想从 students 表中选择所有行。因此,我将使用 pandas 的 read_sql 函数。我将传递我的查询字符串和连接对象。让我们看看。数据被提取后,它会直接转换为数据框,正如您所见。这是我们创建到我的 students 表中的数据。您还可以更新一些记录、删除记录或基于所有这些 SQL 查询命令过滤您的记录。因此,UPDATE students SET Python_marks。基本上,我正在做的是,有一个名叫 Sophia Smith 的学生,我想将她的分数从 78 更新到 95。假设有一个笔误。这就是我想更改的数字。好的。将 78 改为 95。因此,Python_marks = 95,其中姓名是 Sophia Smith。更改后,您应该再次提交您的数据库。好的,这很好。对于查询命令,您不需要提交,但对于更改命令或更新命令,您应该始终提交。您可以验证。因此,我在这里传递我的查询。此查询是原始查询,即 SELECT * FROM students。我再次将相同的查询传递给连接对象。让我们看看它是否已更改。您可以看到 78 已更改为 95。一旦您完成了在内存数据库上的所有 SQL 查询操作,您就可以关闭连接。关闭连接是一个良好的编程实践。这样数据库就可以从内存中释放。好的,也关闭连接。因此,它不再占用您 Python 中的任何内存。完美。接下来,我们将使用 Python 连接到 MySQL 数据库。为此,我们将安装 PyMySQL 和 MySQL Connector。这些是连接 MySQL 数据库到 Python 的两个最流行的连接器。好的。安装完成后,让我们首先使用 PyMySQL 连接器并连接到 Python。因此,导入 PyMySQL 库。这是数据库配置。目前,我的数据库位于 AWS RDS 上。它是一个 RDS 实例。这是 MySQL 数据库在 AWS RDS 上使用的默认端口。RDS 是 AWS 的关系数据库服务。每个数据库都有一个管理员用户名。该管理员用户有一个密码,还有一个数据库名称。因此,在继续之前,请确保您拥有所有详细信息。这也可以是一个托管在您本地机器上的数据库。如果您安装了 MySQL Studio,您就可以在本地机器上创建数据库。在这种情况下,主机将替换为您本地机器的 URL。端口或多或少会保持不变,其他详细信息按需填写即可。这里一个重要的建议是,我们不应该在 Python 笔记本中硬编码这些详细信息。这不是一个好的编程实践。理想情况下,我们应该使用环境变量来存储这些敏感信息,因为如果您与其他人共享此 Python 笔记本,其中填入了所有这些详细信息,他们将能够访问您的数据库并对您的数据库进行不可挽回的更改。他们可以从您的数据库中添加或删除任何内容。因此,将这些详细信息直接放在笔记本中不是一个好的编程实践。稍后,在下一个视频中,我们将看到如何规避此过程。我们将为所有这些数据库配置创建环境变量,并使用用户访问密钥。但现在,为了简单起见,让我们继续。好的。那么,我将执行此操作。现在,我将使用 PyMySQL 的 connect 函数。将所有详细信息传递给该 connect 函数,并开始我的连接。因此,如果打印此消息,则表示我已连接。这里没有错误。就像我们在上一个笔记本中所做的一样。好的。我们将创建一个连接游标,它将执行我的 SQL 查询。一旦创建了我的连接游标,我就传递相同的简单查询 SELECT * FROM students。因此,我的 students 数据库目前在 AWS RDS 实例上。我大概有八条记录。因此,我将其限制为前五条。好的。因此,我实际上正在获取前五行,然后获取所有这五行,然后逐行打印。完成后,您可以关闭连接。好的。所以,它就是这样出现的。因此,您可以看到每一行都作为字典获取。好的。每一行都作为字典获取。我有 student_id、学生姓名、年龄、统计学、Python、机器学习和深度学习分数。现在,让我们看看如何使用 MySQL Connector。因此,首先,您需要安装它。安装完成后,我将导入该连接器以及该 MySQL Connector 的错误类。现在,我们将尝试建立连接。这是一个良好的编程实践,将您的连接建立在 try-except 块中,这样,如果连接到远程数据库时发生任何问题或错误。此错误可能是由于无效的主机名或数据库名称、用户名不正确或密码无效或端口名称错误。这可能是这五个原因之一。您将收到适当的错误。您将能够捕获该错误并打印它。好的,这就是我在这里所做的。因此,如果发生错误,我将捕获该错误并打印它。好的,如果一切顺利,这将打印出“已连接到 MySQL 数据库”。完美。因此,它已连接,并且这部分与之前相同。我只是创建一个游标来执行我的 SQL 查询,然后获取所有五个行并逐个打印。这里的主要区别是,您将输出作为元组获取。您直接获取值。好的。在前一种情况下,您获取键和值。键名是列名。因此,键是列名。好的。抱歉。这是键。这是另一个键。因此,键名基本上是列名,值是它们。因此,它是键值对,即字典。因此,每一行都作为一个字典出现。然而,在这种情况下,您将直接获取每一行中的值作为元组。因此,一个元组代表一行。好的。所以,这是一个区别。因此,您可以决定哪种最适合您的应用程序。好的。好的。这是关闭连接的一种更优雅的方式。如果它已打开,好的,如果已连接,则关闭它。如果未连接,则这两个语句都不会执行。现在,让我们看看如何将 pandas 连接到 MySQL 数据库并使用 pandas 执行直接查询。好的。因此,前两个步骤已完成。您实际上可以使用 MySQL Connector 或 PyMySQL 和 SQLAlchemy。您将需要一个 SQLAlchemy 引擎来连接到 Python pandas,以便您可以发出 SQL 命令。SQLAlchemy 引擎将用于在建立连接后将 SQL 命令传递给 read_sql 函数。因此,这将是必需的。好的。再加上这两个连接器中的一个将是必需的。因此,让我们看看。您需要取消注释此行以安装 PyMySQL 或 MySQL Connector 以及 SQLAlchemy。如果已安装,您可以删除此部分,只需安装 SQLAlchemy 部分。一旦安装了 SQLAlchemy,我就导入 SQLAlchemy 的 create_engine 函数。好的。因此,您首先创建一个连接字符串。您在此处传递用户名、密码、主机名和数据库名称。好的。因此,这是您传递给 create_engine 的连接字符串。因此,您正在创建一个 SQLAlchemy 引擎。让我们看看。完成。因此,我将使用该连接引擎在 pandas 的 read_sql 函数中使用。好的。因此,无论您的查询字符串如何,以及您的连接引擎。因此,这两件事将用于发出任何 SQL 查询并直接将结果作为数据框提取。这是最大的区别。在这里,我们获取了详细信息并逐行打印。好的,我们没有在这里获取数据框。我们也没有在这里获取数据框。因此,在这里,我们将直接将所有详细信息作为数据框提取。这是这里的主要优势。完美。因此,我所有的信息都在数据框中。因此,让我们使用 pandas 的 read_sql 函数执行一些 SQL 查询。第一个查询是相同的,从 students 表中读取所有数据。现在,我将按某个条件过滤记录。例如,我想只提取在 Python 中得分超过 85 的学生。因此,这些是在 Python 中得分超过 85 的学生。您可以检查他们的分数。这些都大于 85。因此,有 20 名学生,索引从 0 到 19。在 20 名学生中,有 16 名学生在 Python 中得分超过 85。接下来,您还可以选择特定列,例如姓名和统计学。因此,SELECT name, statistics_marks FROM students。因此,现在我在这里获取所有学生的姓名和统计学分数。您还可以按特定列对记录进行排序。因此,在这种情况下,让我检索所有学生,并按他们在机器学习科目中的分数进行排序。SELECT * FROM students ORDER BY machine_learning_marks DESC。DESC 表示降序。让我们看看。因此,机器学习分数,并且是降序。好的。另一个 SQL 查询将计算所有学生的平均分数。好的。在统计学课程中。因此,它首先提取统计学科目中的所有分数,然后使用 average 函数计算平均值。因此,提取了统计学,然后计算了 average 函数。因此,84.55 是所有 20 名学生的平均统计学分数。现在,另一个 SQL 查询将计算表中的学生总数。因此,这应该是 20。您还可以按年龄对学生进行分组并计算平均分数。因此,因此,84.75 是所有年龄为 20 岁的学生获得的分数。81.4 是所有年龄为 21 岁的学生获得的分数,依此类推。因此,您可以获得科目平均分。您还可以获得年龄平均分,您可以决定您想做什么。最后一点是,虽然 SQLAlchemy 引擎非常高效,因为查询执行后连接会自动关闭。在这里,您传递了引擎,查询执行后,引擎会关闭与数据库的连接。但可能存在连接未关闭的情况,因为有多个此类连接打开,并且有多个人正在访问同一资源,同一数据库。因此,在这种情况下,一旦完成所有操作,关闭连接是一个良好的编程实践。因此,如果您反复使用此引擎并希望确保所有连接都在最后关闭,那么您可以使用 engine.dispose() 函数。这通常在单次使用时不需要,但如果有多位用户连接到同一数据库并反复执行大量 SQL 操作,那么在所有操作完成后可能需要此操作。好的。因此,在本笔记本的最后一部分,我们将使用 Python 连接到 PostgreSQL 数据库。因此,正如在上一视频的演示中讨论的那样,我将使用 psychopg2 包。因此,首先尝试使用此命令安装 psychopg2。因此,首先尝试使用此命令安装 psychopg2。因此,只需取消注释此行并执行。如果安装有任何错误,请尝试下一个。这取决于机器和服务器。好的,配置。因此,有时第一个会起作用,或者下一行会起作用,但请按该顺序尝试。我已经安装了 psychopg2 库,然后,像往常一样,您有数据库配置。因此,这是 PostgreSQL 数据库,它再次托管在我的 AWS RDS 实例上。因此,这是端点。PostgreSQL 数据库连接通常默认使用端口 5432。这是我的数据库名称。我的数据库的管理员用户名和密码。因此,有了这些,我将开始连接。因此,导入 psychopg2 库,然后也导入错误。像我们之前一样,使用 try-except 块是一个良好的编程实践。因此,在这里,我创建了一个函数来创建连接。因此,这样做的优点是,我可以直接调用此函数,它将直接创建连接,并返回该连接。因此,我可以在我的 pandas 中直接使用此连接。其他事情都非常不言自明。我们一直在这样做。要再次执行 SQL 查询,我正在创建一个函数。因此,它需要连接和查询。在与该连接建立游标后,它将执行该查询,然后最终提交,并将显示任何结果。因此,与 PostgreSQL 数据库的连接已成功。这是我将在此处传递并执行该查询的查询。因此,此查询已执行,然后您可以关闭连接。因此,如果您想再次使用 pandas 的 read_sql 函数,以便查询的所有结果直接转储到 pandas 数据框中。那么您必须再次回到 SQLAlchemy 引擎。因此,再次是相同的连接字符串。因此,这是唯一不同的地方。因此,数据库的名称意味着数据库的类型。因此,之前是 MySQL,然后是连接器的名称。因此,在上一例中,我们使用了 MySQL 连接器。在这里,我使用的是 psychopg2 连接器,然后其余部分保持不变,其余代码也保持不变。您创建一个 SQLAlchemy 引擎,然后定义一个查询,然后使用该连接执行该查询。好的,让我们看看。完美。因此,我能够连接到相同的数据库并检索所有记录。现在,与 MySQL 连接器相比,psychopg2 的优势在于,与 SQLAlchemy 引擎一样,psychopg2 也直接为您提供与数据库的持久连接。好的,我们在 read_sql 函数内使用了 SQLAlchemy 引擎。psychopg2 的好处是,您实际上可以使用 psychopg2 创建的连接直接向数据库发出 SQL 查询。好的,虽然不推荐这样做,这就是为什么会出现此警告。因此,pandas 只支持 SQLAlchemy 可连接对象,而我们之前已经这样做了。虽然它有效,但它不安全,也不受支持。它只是有效,并且还建议我们使用 SQLAlchemy 而不是它。好的,这正是我们刚才所做的。因此,不推荐这样做。但是,它有效。万一您想尝试。最后,一旦您完成,请不要忘记关闭您的连接。大家好,欢迎观看关于 API 的视频。在本视频中,我们将探讨 API 在软件应用程序中扮演的关键角色,尤其是在 AI 代理和大型语言模型方面。API 是现代技术的重要组成部分。它们使不同的系统能够相互通信,使我们能够将强大的功能集成到我们的应用程序中。让我们深入了解一下。今天我们将涵盖以下内容。我们将从定义什么是 API 以及为什么它很重要开始。然后,我们将深入研究 RESTful API 和 JSON 数据格式,这些是基于 Web 的 API 的基础概念。我们将学习如何使用 Python 的 requests 库访问 API,然后是最佳实践,如处理速率限制、错误和身份验证。最后,我们将讨论 API 如何与 LLM 交互以及 AI 代理的创建,以及如何与托管在其他服务器上的这些代理和 LLM 进行交互。什么是 API?让我们先回答这个问题。API 代表应用程序编程接口,它本质上是一组允许不同软件应用程序相互通信的规则。将 API 想象成餐厅里的服务员。您作为顾客下单。这就像发送请求。服务员将您的订单送到厨房。这就是服务器,然后带回您的食物。基本上是服务器的响应。API 的工作方式非常相似。它们接收请求,处理它们,然后返回结果。API 如何工作?API 就像一个信使,它接收请求并告诉系统您希望它做什么,然后将响应返回给您。它定义了各种软件组件之间的通信方法。例如,当您使用手机上的应用程序时,该应用程序会连接到互联网并将数据发送到服务器。然后,服务器会检索该数据,对其进行解释,执行必要的操作,然后将其发送回您的手机。然后,该应用程序会解释该数据,并以可读的方式向您呈现您想要的信息。为什么 API 很重要?API 很重要有几个原因。互操作性。它们使不同的系统能够协同工作,从而无缝地共享数据和服务。可扩展性。API 可以支持多个客户端,允许不同的平台访问相同的核心服务。可复用性。您可以通过 API 使用现有服务,而无需从头开始构建新功能。创新。API 通过让开发人员能够访问强大的功能和可访问性来鼓励新应用程序的开发。它们使外部托管的数据和服务也能被访问,否则这些数据和服务将难以访问。例如,使用 Google Maps API,开发人员可以轻松地集成地图和地理定位功能,而无需从头开始构建自己的地图系统。API 的真实世界示例。API 无处不在。当您使用 Facebook 或 Google 帐户登录网站时,API 正在发挥作用。当应用程序向您显示地图或您当前的位置时,它正在使用映射服务的 API。支付网关使用 API 安全地处理交易。甚至聊天机器人和虚拟助手也使用 API 来理解和响应您的用户输入。这些只是 API 使我们的数字交互无缝高效的几个例子。API 在 LLM 和 AI 代理方面的应用。API 在人工智能领域发挥着重要作用。API 允许开发人员访问预训练模型和服务的,如 OpenAI 的 GPT 模型、Hugging Face 模型和 Google Cloud AI 服务,而无需从头开始构建这些模型。使用这些 API,您可以将计算复杂性卸载到外部服务器,从而无缝地将高级 AI 功能集成到您的应用程序中。这包括自然语言处理、语言翻译、情感分析甚至推荐系统等内容。API 使人工智能易于访问,而无需深入的模型开发专业知识。通过 API 与 LLM 交互通常涉及将提示或用户输入发送到 API,API 使用复杂的语言模型对其进行处理,然后返回生成的响应。例如,使用 OpenAI API,您可以发送一个提示并获得一个完成。虽然这很强大,但需要考虑延迟(由于网络通信)、与 API 使用相关的成本以及数据隐私问题(尤其是在通过网络发送敏感信息时)。大家好,欢迎观看关于使用 Python 访问 API 的视频。在本视频中,我们将探讨如何在 Python 中处理 API,重点关注与 Web 服务交互和提取数据的实用技术。API 是许多数据驱动应用程序的核心,学习如何使用 Python 访问它们是任何数据科学家或 AI 开发人员的一项基本技能。让我们开始吧。在深入研究代码部分之前,让我们先了解一下 HTTP 协议的基础知识。HTTP,即超文本传输协议,是 Web 上数据通信的基础。它定义了客户端和服务器之间请求和响应的结构。在处理 API 时,您将使用几种 HTTP 方法。GET 用于检索数据。POST 用于向服务器提交新数据。PUT 用于更新现有数据。DELETE 用于删除数据。这些方法允许我们与远程服务器上的数据进行交互。理解这些 HTTP 方法是处理任何 API 的关键。此外,您还会遇到状态码。例如,200 表示成功,404 表示找不到资源,500 表示服务器错误。这些代码可帮助您了解您的请求是否已成功处理,或者是否存在任何问题。RESTful API。大多数现代 API 都根据 REST 架构进行设计。Representational State Transfer。REST 是一种用于设计应用程序的架构风格。它依赖于几个核心原则。无状态性。服务器不存储任何客户端状态。这意味着客户端的每个请求都包含服务器完成该请求所需的所有信息。客户端-服务器架构。这会将用户界面与数据存储分开,从而简化应用程序与 API 的交互方式。统一接口。所有 API 端点都使用标准方法和格式,使其更易于使用和理解。可缓存性。响应可以缓存以提高性能。RESTful API 使用 GET、POST、PUT 和 DELETE 等 HTTP 方法进行 CRUD 操作,包括创建、读取、更新和删除操作。一旦您理解了这些原则,它们就很容易使用。RESTful API 交互涉及几个组件。端点或资源 URL 指定资源的位置。HTTP 方法指示您要对资源执行什么操作。标头承载元数据信息,如内容类型或身份验证令牌。这有助于服务器理解如何处理请求或谁在发出请求。正文或有效负载包含您发送到服务器的数据,通常采用 JSON 格式。最后,在预处理您的请求后,服务器会以 JSON 格式发送响应,其中也包含标头和请求的数据。理解这些组件对于有效处理 API 至关重要。JSON 是 API 最常用的数据格式。它轻量级,易于人类和机器阅读和编写。JSON 使用键值对来构建数据,非常类似于 Python 字典。在示例中,我们有像 name 和 age 这样的键,以及相应的键值。在处理 API 时,您将经常以 JSON 格式发送和接收数据。因此,理解它至关重要。Python 使与 API 的交互变得简单。有几个库可用于 API 访问,但两个最常用的库是 requests。此库简化了 HTTP 请求的创建,并为您处理了大部分复杂性。URLlib 是一个标准的 URL 处理库,虽然它可能比 requests 稍微麻烦一些,但我们通常使用 requests 库,因为它用户友好、简洁且支持所有 HTTP 方法。它非常适合进行 API 调用、管理会话甚至处理 cookie,所有这些都只需几行代码即可完成。requests 库的介绍。要开始使用 requests 库,您需要使用 pip install requests 进行安装,然后您可以将其导入到您的 Python 脚本中。该库支持您需要的所有 HTTP 方法,并简化了处理查询参数和有效负载等任务。它还提供包含状态码和 API 返回内容的响应对象。官方文档是了解其更多功能的绝佳来源。发送请求。GET 请求用于从 API 检索数据。让我们看一个从 API 获取公共数据的示例。您可以使用 requests.get 函数通过传递 URL 作为参数来发出 GET 请求。如果您需要包含查询参数,可以使用 params 参数将它们作为字典传递。响应对象包含状态码、文本内容,如果响应是 JSON 格式,则可以将其作为 JSON 传递。requests 库返回的响应对象提供了几个有用的属性。您可以检查状态码以确定请求是否成功。状态码 200 表示成功。headers 属性包含响应标头,text 将原始内容作为字符串提供。如果响应是 JSON 格式,您可以使用 response.json() 函数进行解析。在处理响应之前,请务必检查状态码以适当处理错误。发送 POST 请求。POST 请求用于将数据发送到服务器。例如,在提交表单或将数据上传到 API 时。您可以使用 data 或 json 参数在请求中包含数据。发送 JSON 数据时,通常将 content-type 标头设置为 application/json。当您使用 json 参数时,requests 库会为您处理此问题。通过 API 与 LLM 交互通常涉及将提示或输入文本发送到 API,API 使用复杂的语言模型对其进行处理,然后返回生成的响应。例如,使用 OpenAI API,您可以发送一个提示并获得一个完成。当 API 以 JSON 格式返回数据时,您可以使用 response.json() 函数进行解析,该函数将其转换为 Python 字典。然后,您可以使用键像任何字典一样访问单个数据点。如果数据是嵌套的,您可能需要访问多个键级别。理解 JSON 响应的结构对于正确解析和使用数据至关重要。让我们从 API 的最佳实践开始。阅读文档。请务必仔细阅读并理解 API 文档。这将帮助您了解 API 使用的端点、参数和身份验证方法。优雅地处理错误。实施健壮的错误处理来管理连接问题、不正确的输入或服务器错误等问题。尊重速率限制。大多数 API 都设有速率限制以防止滥用。超出这些限制可能会导致您的访问被暂时甚至永久阻止。安全保管您的 API 密钥。API 密钥是敏感信息。安全地存储它们。使用环境变量或安全的存储机制。验证输入和输出。确保所有输入和输出都经过正确验证,以维护数据完整性并防止安全漏洞。最后,使用日志记录。记录 API 请求和响应。这有助于调试问题并了解交互过程中出了什么问题。遵循这些最佳实践将使您的 API 集成更加可靠和安全。API 请求中的错误处理。错误处理是与 API 交互的关键部分。以下是一些常见的 HTTP 状态码及其含义。400 Bad Request。请求无效,可能是由于语法不正确。401 Unauthorized。访问此资源需要身份验证。403 Forbidden 表示服务器理解请求但拒绝授权。404 Not Found 错误。这意味着您尝试访问的资源不存在。500 Internal Server Error。这意味着服务器本身出了问题。处理错误的最佳实践包括:第一,始终检查状态码。这有助于您了解请求是否成功或是否存在问题。使用 raise_for_status() 方法自动引发错误代码的异常,这确保在 Python 脚本中处理错误。适当的错误处理使您的应用程序更加健壮,确保即使出现问题,您的用户体验到的中断也最小。API 速率限制。现在,让我们谈谈 API 速率限制。速率限制涉及限制客户端在给定时间段内可以向 API 发出的请求数量。速率限制的目的是防止滥用并避免服务器过载。超出此限制可能导致错误或暂时被阻止。它还确保不同客户端之间的公平使用。为了有效地处理速率限制,请检查标头。许多 API 在响应标头中包含速率限制信息,例如剩余请求数。您还可以实现延迟。为此,您可以使用 time.sleep() 函数在接近限制时等待,然后再发出新请求。最后,您还可以使用指数退避。如果您遇到速率限制错误,请在每次重试后逐渐增加等待时间。尊重 API 的速率限制并监控应用程序的请求速率以避免服务中断至关重要。身份验证对于保护 API 和控制对资源的访问至关重要。它确保只有授权用户才能访问某些数据或功能。常见的身份验证方法包括 API 密钥、OAuth 2.0 和 Bearer 令牌。现在,让我们逐一讨论身份验证类型。让我们从 API 密钥开始。API 密钥是身份验证请求的简单而有效的方法。在向 API 提供商注册后,您将收到一个标识您的唯一密钥。您可以在请求中包含此密钥,可以在标头中,也可以作为查询参数。为了安全起见,最好将其包含在标头中。请记住安全保管您的 API 密钥。不要在脚本中硬编码它们或公开共享它们。使用环境变量或安全的存储机制来保护它们。现在,让我们谈谈 OAuth 身份验证,它是一种开放的访问委派标准,允许第三方应用程序在不共享密码的情况下访问用户数据。Google、Facebook 和 Twitter 等平台使用 OAuth 来提供安全访问。OAuth 流通常涉及以下步骤。首先,生成身份验证请求。用户被重定向到授权服务器以授予访问权限。然后,用户进行身份验证并授权访问。在下一步中,服务器返回一个授权码,应用程序可以将其交换为访问令牌。最后,此访问令牌用于代表用户发出 API 请求。OAuth 实现起来更复杂,但提供了增强的安全性,使其成为用户需要安全地授予对其数据的访问权限的理想选择。让我们总结一下本模块的学习内容。首先,我们了解到 API 是实现不同软件系统之间通信的基本工具。理解 RESTful API 和 JSON 数据格式的基础知识至关重要。Python 的 requests 库提供了一种简单的方法来与 API 进行交互。遵守最佳实践可确保您的应用程序健壮且安全。API 在与 LLM 协作和构建代理方面发挥着重要作用。提供对高级功能和数据的访问。大家好,欢迎观看关于使用 Flask 和 FastAPI 构建 API 的视频。在本视频中,我们将探讨如何使用两个流行的 Python 框架 Flask 和 FastAPI 来创建 RESTful API。我们将涵盖设置端点、处理 GET 和 POST 请求的基础知识,以及使用 Postman 等工具测试我们的 API。我们还将比较 Flask 和 FastAPI,以帮助您了解哪个可能更适合您的项目。Flask 是用 Python 编写的微框架。它被称为微框架,因为它不需要奇异的工具或库,使其轻量级且易于上手。当我们说 Flask 用于构建 Web 应用程序和 API 时,我们的意思是它可以处理前端(即我们在浏览器中看到的内容)以及后端(即 Web 开发的服务器端逻辑和数据处理部分)。Flask 提供了构建 Web 应用程序和 API 的基本组件,如路由、请求处理和开发服务器。它的简单性和灵活性使其成为想要对其应用程序进行更多控制的开发者的热门选择。让我们分解一下使用 Flask 创建端点的过程。首先,您需要导入 Flask 并创建一个 Flask 应用程序实例。这通常使用 app = Flask(__name__) 来完成。Flask 中的第二步是使用装饰器来定义路由。装饰器是一种特殊的 Python 语法,以 @ 符号开头。它是一种修改或增强 Python 函数的方式。路由是您 API 的 URL。例如,/hello 或 /users。GET 和 POST 等 HTTP 方法定义了我们正在执行的操作类型。GET 通常用于检索数据,而 POST 用于发送要处理的数据。最后,我们可以使用 python app.py 命令在终端或命令提示符中运行应用程序。可以从浏览器窗口访问我们创建的端点,如下所示。现在,让我们看看使用 GET 方法处理用户请求的端点创建过程。第一步,我们将导入 request 模块以访问请求数据,以及 json 模块以进行 JSON 响应。然后,我们将使用 methods 参数来指定 HTTP 方法来定义路由。正如您在第 6 行所看到的,我们正在定义路由,methods = ['GET']。然后,在第 8 行,我们正在访问数据。如果有效负载以 JSON 格式传入,您也可以通过 request.get_json() 来完成此操作。最后,如果我们想要 JSON 格式的响应,我们将使用 json 函数返回响应。应用程序创建完成后,您可以运行应用程序,然后可以从浏览器窗口访问该应用程序。我们必须转到 localhost,它可以在端口 5000/get_data 处访问,这是我们在这里创建的端点的名称。这是另一个使用 GET 方法从用户请求输入的端点。因此,@app.route('/square') 是端点的名称,methods = ['GET'] 再次。因此,此 app 端点需要用户提供一个数字,默认情况下该数字为零。如果用户未提供任何输入,我们将使用零。因此,我们返回的是该数字的平方。因此,这是一个字典,大多数情况下与您的 JSON 格式相同。最后,我们可以运行此应用程序并通过浏览器窗口访问它。您可以看到,我们有 localhost:端口号 5000/square。因此,/square 是您的端点,后面跟着一个问号,然后是参数的名称,即用户必须提供的数字,等于用户必须提供的实际数字 5、10、15、500,无论该数字是什么,我们都想计算其平方。现在,在此示例中,我们有两个端点,一个用于 GET,另一个用于处理 POST 请求。/get_data 路由响应 GET 请求,返回一个简单的 JSON 消息。post_data 路由处理 POST 请求。它使用 request.get_json() 函数检索请求正文中发送的 JSON 数据,并返回一个包含接收到的数据的响应。因此,通过在 app.route 装饰器中指定 methods 参数,我们定义了每个端点接受哪些 HTTP 方法。现在,有几种方法可以访问和测试您的 API 端点。第一种方法是浏览器地址栏。这仅适用于 GET 请求。只需键入端点的完整 URL 并按 Enter 键。第二种方法是使用命令行工具。您可以使用 curl,这是一个用于传输数据的命令行工具,或者您可以使用 wget,这是另一个命令行工具。Postman 等 API 测试工具也可以使用。它们提供了一个用户友好的界面,用于发送各种类型的 HTTP 请求并查看响应。因此,要测试我们的端点,我们可以简单地打开 Web 浏览器并导航到 http://localhost:5000(这是 Flask 应用程序通常访问的端口),然后加上一个斜杠,然后是端点的名称。浏览器将显示来自服务器的 JSON 响应,或者我们也可以使用终端中的 curl 命令发出相同的 GET 请求。但是,由于浏览器本身不支持从 Web 浏览器地址栏发送具有 JSON 正文的 POST 请求,因此我们可以使用 curl 发送带有 JSON 有效负载的 POST 请求,或者您也可以通过 Python 代码访问 POST 端点。因此,此命令必须包含标头以指定内容类型,然后还使用 -d 标志来包含数据。使用 Postman 测试 API。因此,Postman 是一个非常广泛使用的 API 开发和测试工具。它提供了一个直观的界面,您可以在其中配置具有不同方法、标头和正文的请求。要测试我们的 API,我们可以创建一个新的 Postman 请求。指定端点 URL,然后选择适当的 HTTP 方法。您可以从这个 URL 免费下载 Postman。要使用 Postman 测试我们的 API,我们可以创建一个新的 Postman 请求。在此指定端点 URL,然后从下拉列表中选择适当的 HTTP 方法,GET、POST 等等。对于 POST 请求,我们需要在请求正文中包含一个 JSON 有效负载。然后,我们最后单击发送。然后,Postman 将显示来自服务器的响应,使我们能够验证我们的 API 是否按预期工作。Postman 使
测试不同场景和调试我们的 API 非常容易。FastAPI 是另一个用于使用 Python 构建 API 的现代 Web 框架。它被设计成快速且非常易于使用。它利用 Python 的类型提示来提供自动数据验证、序列化和交互式文档,并内置异步支持。FastAPI 支持构建高性能应用程序。它对开发者体验的关注使其成为快速创建健壮且可扩展 API 的热门选择。因此,比较 Flask 和 FastAPI。Flask 和 FastAPI 都是强大的框架,但它们各有优势。Flask 简单明了,是初学者和小项目的不错选择。但是,它可能需要额外的插件或手动编码来实现数据验证和文档等功能。另一方面,FastAPI 提供了高性能和现代功能,如异步请求处理和自动文档生成。它广泛使用 Python 类型提示,可以强制执行数据验证并提高代码质量。最后,虽然 FastAPI 由于依赖类型提示,学习曲线略陡峭,但它可以显著加快需要健壮功能和可扩展性的 API 的开发速度。本视频到此结束。在下一个视频中见,我们将深入探讨 API 创建和使用 Flask 框架访问这些 API 的实践。欢迎回到这个另一个 Flask 编码教程。在本教程视频中,我们将创建和访问端点。所以,让我们首先从创建一个简单的 Flask 应用开始。在这种情况下,我正在创建一个简单的应用,它将向用户问好“hello world”。让我们看看 Flask 应用的结构。首先,我从 Flask 库导入 Flask 类。默认情况下,如果您使用 Anaconda 甚至 Google Colab,Flask 都会预装。但如果您的机器上没有安装 Flask,您应该在运行这些代码之前执行 `pip install flask`。好的。由于我已经安装了 Flask,我们将继续。这是我正在创建的 Flask 应用,以及我们如何初始化 Flask 应用。`app = Flask(__name__)`。这是我们创建端点的地方。这是我的根端点。对于每个端点,我们都必须定义一个函数。基本上,它告诉用户当用户访问此端点时应该执行什么操作,应该执行什么活动,这在函数内定义。好的。这是装饰器,它本质上装饰了这个函数。好的。所以,每当我访问这个端点时,这个函数就会被触发,而这个函数所做的就是简单地将“hello world”返回给用户。好的。从这段代码开始,我将运行 Flask 应用。理想情况下,应该使用 `.py` 文件运行整个代码。从 Jupyter Notebook 中运行 Flask 应用程序或端点不是一个好习惯。好的。但为了简单起见和学习,我们在这里这样做。但理想情况下,这应该被包装在一个 `python.py` 文件或 `app.py` 文件中。然后应该使用您的终端运行该 `app.py` 文件。好的。所以,让我运行它。它说我正在以调试模式关闭的状态提供此 Flask 应用。这是它运行的 URL。所以,让我点击这个 URL。瞧,您可以看到 Flask 应用已将“hello world”返回给我。好的。每当我访问该端点时,它都会被提供。这非常容易。您也可以使用 `curl` 命令访问此 URL。所以,我将复制它。`curl` 命令可以从您的命令提示符访问。我正在运行我的命令提示符 `cmd`。在这里,我可以直接粘贴我的 `curl` 命令并按 Enter。您可以在此处看到输出为“hello world”。对?好的。所以,我必须停止它。我该如何停止它?那里有一个中断终端或中断内核按钮。所以我将点击这个中断内核来中断或停止 Flask 服务器。完成。现在让我们转到下一个路由。在这里,我们将创建一个应用路由,它接受用户输入并执行一些计算。所以,我们这里将有两个应用路由。一个是问候用户并带有一些名字,这个名字将由用户提供。好的。所以,如果我提供“Prashant”,它将以 H1 标题问候“hello Prashant”。这是我用它包装的 HTML 代码。好的。其次,创建了另一个名为 `/square` 的端点,它期望一个整数作为数字。好的。所以,当用户提供该数字时,我将对该数字进行平方,并将其包装在此 HTML 字符串中,然后将其显示回浏览器窗口。让我们看看。所以,这个 Flask 应用正在运行。好的。现在如果我点击它,它会说 URL 未找到,因为根 URL 或根应用中没有定义任何内容。好的。根端点。好的。在此 Flask 应用中定义的唯一端点是 `greet` 和 `square`。好的。所以,我应该只访问 `greet` 和 `square` 端点。所以,我将要做的是,让我复制我的 `greet` URL。好的。我将在这里复制并粘贴我的名字。所以,现在您可以看到“hello Prashant”。所以,如果我只是在 URL 中更改名字,例如“Amy”,您可以看到响应是“hello Amy”。好的。所以,`greet/greet` 是我的端点,除此之外是用户输入,这正是这个端点所做的。它接受用户输入作为名字,并显示“hello [名字]”。另一个是 `square`。所以,您可以在这里访问它。所以我将复制它并替换它。所以我可以提供一些数字。例如,100。所以,这是提供的数字,这是该数字的平方。好的。如果您愿意,您也可以使用 `curl` 命令访问此 URL。所以,您所要做的就是输入 `curl`,然后是端点 URL 以及用户输入。这非常重要。如果您忘记了用户输入,您将收到一些错误。好的。所以,让我们看看如果我忘记用户输入会发生什么。好的。它说 404 未找到。此错误主要是因为未提供用户输入。我正在尝试在未提供用户输入的情况下访问端点。此错误消息也在此处记录。好的。404。好的。所以,200 表示状态“OK”,表示请求成功,响应已成功生成并提供给用户。所以,200 是好的。404 是不好的。好的。现在,您可能希望实际提供一个名字。例如,让我回去。我的全名是 Prashant Sahu。所以,如果我尝试输入一个空格,如果在这里地址栏中看到,它会自动附加一个百分号。这是我提供的空格的 URL 编码。好的。所以,`%20` 是完整的 URL 编码。所以,如果您想在用户输入中使用特殊字符,请确保 URL 已正确编码。所以,您可以查看 W3Schools 的 URL,以获取有关 URL 编码的完整参考。还有一个链接可以帮助您免费在线生成 URL 编码。所以,一旦我输入我的名字,比如 Prashant Sahu,您可以看到空格会自动用 `%20` 编码。所以,这应该是完整的用户输入。所以,假设明天我想换个名字,比如 John Doe。这是我自动获得的。所以,这需要复制,然后我可以将其粘贴到我想访问 URL 的地方。所以,`greet` 然后删除这个。粘贴。按 Enter。太棒了。所以,这使得 API 调用非常安全。您也可以使用我已经在其他路由中完成的错误处理。所以在第三个例子中,我实际上将进行一些错误处理,正如刚才提到的。好的。所以,在这个例子中,我将显式使用 `GET` 方法。事实上,如果您注意到,在前面两个端点中,我们也可以使用 `GET` 方法访问端点。所以,即使您没有在此处提及方法列表,`GET` 方法也是默认启用的。好的。在下一个例子中,我将显式提及允许该端点的哪些方法。所以,这里 `GET` 方法是允许此 `square root` 端点的唯一方法。所以,这个 `square root` 端点被编程在这里接受两个数字作为输入。我将除以这两个数字,并将结果数字馈送给平方根函数。所以我将计算除法结果的平方根。所以,将有两个数字作为输入。这两个数字将被除以,然后将除法结果用于平方根。该平方根将作为结果返回给用户,该平方根将作为结果返回给用户以及除法结果。好的。所以,这次有两个输出。一个是除法结果,另一个是平方根。所以,如果您仔细查看定义,我已将整个代码包含在 `try-except` 块中。所以,这两个数字将从用户那里请求 `num1` 和 `num2`。如果任一数字未提供,它将引发此错误。如果第二个数字为零,我们将得到零除法错误。否则,如果一切正常,我们将计算除法结果。如果其中一个数字为负数,无论是分子还是分母。如果其中一个为负数,则无法执行平方根运算,因为负数的平方根是复数。所以,在这里处理起来有点困难。所以我只是抛出那个错误,因为其中一个数字是负数。如果所有条件都满足,则执行此操作。好的。所以,让我们执行它。好的。现在我的应用正在运行。哦,我想我忘了停止我之前的应用。好的。这就是为什么我没有在这里收到响应。好的。我应该收到类似“serving flask app main”的响应。所以,让我停止它。好的。确保它已停止并再次运行。好的。是的。所以,现在它正在提供服务。所以我可以访问这里的其中一个 URL。我已经提供了这些 URL。您可以直接点击访问,也可以复制粘贴。好的。所以,第一个数字是 16。第二个数字是 4。所以,除法结果是 4,4 的平方根是 2。好的。这很好。现在我在这里收到一个错误,因为我只提供了数字 1 而没有提供数字 2。请求只提供第一个数字,而不提供第二个数字。由于第二个数字丢失,我收到此错误。好的。下一个请求,第二个数字是零。如果您看到,这就是为什么这里出现零除法错误,最后,这里的第一个数字是负数,这就是为什么出现最后一个错误。我们无法计算负数的平方根。您也可以通过 `curl` 访问所有这些端点。所以,让我给您展示其中一个。假设您从这里复制到这里,然后回到您的命令提示符并粘贴 URL。是的。所以我在这里收到响应。所以,整个响应是 HTML 格式,如您所见。好的。在 H1 标题内。完美。所以在下一个例子中,我将演示 `POST` 方法及其一些变体。好的。所以,我在这里启用了 `GET` 和 `POST` 方法。所以,当用户想将数据作为 HTML 表单或某些 JSON 负载发布到服务器时,通常使用 `POST` 方法。好的。当用户想从服务器请求数据或从服务器下载数据时,通常使用 `GET` 方法。所以,在这种情况下,表单期望 `message` 字段。好的。默认情况下,如果用户未提供任何消息,它将采用“no message”作为输入。好的。所以,我在这里创建一个将被渲染的表单。好的。所以,这个表单的 `action` 是 `sub`,在这里您将创建一个文本字段,然后是一个提交按钮,一个带有文本字段和提交按钮的简单表单。好的。所以,一旦按钮被提交,`request.post` 方法就会被接受。好的。在这种情况下,这是返回的内容。好的。相同的消息与此字符串一起返回。所以,让我们显示此表单。好的。我再次必须停止之前的。好的。现在它正在提供服务。所以我可以在这里访问此表单。所以,您可以看到左上角有一个小表单,然后,让我在这里提供一些消息。所以,“hello world this is flask app”,然后点击提交。所以,这就是您提交给服务器的内容,对吗?完美。所以,这有效,您也可以通过 `curl` 访问它。好的。所以我只是停止它。现在,如果您想通过 Python 代码访问相同的 `POST` 表单,您想通过 Python 代码向服务器提交 `POST` 请求。好的。您不想填写此表单。基本上,您不想填写此表单。好的。您刷新它,它会再次为您提供表单。所以,假设您不想填写此表单。那么,这就是您需要的代码。好的。所以,我将复制这段代码。运行此 Flask 应用。好的。运行此 Flask 应用。您不能在同一个笔记本中运行此代码,因为您不能在同一个笔记本中运行多个代码。所以我将创建一个临时笔记本,我在其中粘贴该代码以运行它。好的。所以,这段代码将访问您的 Flask 应用,使用 `POST` 方法。所以,这是我将发送请求的 URL。好的。所以,这是 URL,这是我本应在前端输入的 `message`。对?所以,这是,让我刷新一下。好的。所以,是的,这里。所以,您想在这里输入任何内容,您只是想从后端提交。好的。所以,您通过这个 `data` 字典将相同的消息传递给服务器。好的。所以,您可以使用 `POST` 方法,传递 URL 和数据。好的。然后从服务器收集响应并提取响应中的文本部分。让我们看看。完美。所以,这是我从服务器获得的响应。响应中还有很多其他内容。让我们快速看一下。第一个是 `headers`。所以,您可以检查 `headers`。好的。所以,响应头包含请求发送到服务器的日期和时间。好的。内容类型、字符集、内容长度(本质上是 43 个字符),以及连接当前是否已关闭。这是 `work zug server`。这本质上是 Flask 服务器。好的。否则,一旦应用程序托管在真实服务器上,实际服务器的 URL 将在此处显示。对?您还可以查看 `response.text`。您可以看到其他内容,如 `history` 和响应的 JSON 格式。让我们选择 `status`。好的。这是 `status` 代码。所以,如果一切成功,它们应该返回 200。所以,状态代码 200 表示服务器成功满足了请求,没有任何错误。好的。还有很多其他内容您可以探索。好的。回到应用,让我停止它。我创建了这个 Flask 应用的一个小变体。所以,在这个例子中,这个 Flask 端点被修改为接受 JSON 数据。好的。所以我将不再使用字典输入。事实上,如果您在这里看到,主要区别在于 `get from form data`。它将以 JSON 格式获取数据,而不是将表单数据作为字符串获取。`request.get_json()`。好的。所以,这是它感兴趣的字段,用于提取消息,并且响应也被 JSON 化了。所以,这里响应直接以 HTML 格式给出,但现在我将整个响应 JSON 化了。所以,响应将以 JSON 格式出现。所以,这段代码是相同的。好的。让我运行它,再次访问它,我将复制这段代码。所以,如果您从前端访问它,它与这里不会有太大差别。让我们看看。好的。所以,我将要解析的 JSON 数据是 `message`。所以,这很重要,因为服务器会搜索这个字段。好的。用于处理您的请求。好的。所以,这是您正在访问的 URL,并且此 JSON 数据被解析到这里的 `json` 参数。现在,从 `response.json()`,您可以获取您的整个输出。所以,`response.json()` 是您感兴趣的,对吗?完美。所以,让我停止它,最后,我们将创建一个几乎端到端的应用,包含前端和后端。好的。这是一个相当高级的应用,带有 HTML 模板,并由 Jinja 库和 CSS 渲染支持。好的。对于初学者来说,理解整个代码库可能会有点棘手。我强烈建议您复制它,粘贴到 ChatGPT 中,并要求 ChatGPT 逐行解释,这将非常容易。我假设您对 Python 编码相当熟悉,因此我将只从高层次解释正在发生的事情。所以,这与我在这里使用的代码非常相似。我之前为 `GET` 方法使用的。好的。只是现在将其转换为 `POST` 方法。好的。只是转换为 `POST`。所以,第一个区别是,我在这里添加了一个 `home` 路由,基础路由。好的。所以,您可以访问它。这很重要。好的。我们以前没有这样做过。所以,这是一个根路由。所以,这里将渲染 HTML 页面。在这个 Flask 应用中将使用三个 HTML 页面。一个是主页。第二个是表单页面。所以,这是我们之前通过 Python 代码即时创建的表单。而不是即时创建这个表单,我已经创建了这个表单并将其单独保存为 HTML 文件。对?所以,那个表单 HTML 已单独创建。所以我不会打开那个 HTML 代码并在此处解释。请随时自行查看,如果您有任何问题或疑问,请告诉我。您可以寻求 ChatGPT 的帮助来解释表单 HTML 代码,因为其中有很多 HTML。好的。所以,这两件事都很清楚。一个是 `home.html`,表单 HTML 将创建一个用户需要输入两个数字的表单。最后,如果一切顺利,计算将发生,结果将显示在另一种 HTML 格式中。好的。所以,该 `result.html` 与您的实际计算结果一起被渲染。如果这里发生任何错误,它将进入 `except` 块,并且会得到妥善处理。好的。所以,让我执行它。好的。所以我将简单地点击这里。它转到 `home.html` 页面。所以,这本质上是 `home.html`。我点击这个是为了进入我的计算器应用。我将在这里输入两个数字。所以,假设第一个数字是 12345。第二个数字是 25。所以,首先要做的是将这个数字除以这个数字,结果是 493.8,它的平方根是 22.22。对?所以,点击这个,它会回到主页。对?所以,整个事情,让我再次向您展示主页是这个应用的基础路由。点击这个。它转到哪个端点?它转到 `square root` 端点,其中渲染了 `form.html`。一旦我输入了一些数字,点击提交按钮。这是我的提交按钮。它实际上转到 `results.html`。所以,这是来自 `results.html`。完美。如果您注意到一些东西,有 304,304,这在之前的任何运行中都没有出现过。304 从未在这里出现过。所以,这是新东西。所以,304 不是错误。它实际上告诉您,我正在缓存服务器中的 CSS 和 HTML 文件,并且缓存版本被呈现给用户。所以,304 未修改是一个 HTTP 状态码,表示请求的资源。我们请求什么资源?三个 HTML 文件和一个 CSS 文件。我们正在访问。所以,自上次请求以来,这些文件没有被修改。所以,这种缓存有助于服务器非常快速地加载这些文件,并且还减少了服务器负载和数据传输。您必须注意的一件重要事情是这些 HTML 文件在本地的文件夹组织方式,以便在运行 Flask 应用时正确渲染 HTML 文件。所以,这是运行 Flask 应用的 Jupyter Notebook。这可以是一个您用来运行 Flask 应用的常规 Python 文件。这是将渲染您的 Flask 服务器的文件。在此文件夹本身内,我还有两个文件夹。一个是名为 `templates`。所以,`templates` 文件夹包含 HTML 模板。表单和表单的结果将被显示,以及主页。这些都是我们在 Flask 应用中使用的 HTML 文件。还有一个名为 `static` 的文件夹。这个 `static` 文件夹包含 CSS 文件。现在,这个 CSS 文件已附加或链接到所有 HTML 文件。好的。所以,当我打开任何一个 HTML 文件时,您可以看到这个样式表已经被引用了。您可以看到这个样式表已经被引用了。这就是为什么您需要将 CSS 文件放在 `static` 文件夹中的原因。CSS 文件是用于样式化网页前端的文件。好的。它包含样式信息。什么颜色、什么背景、按钮应该是什么样子?文本字段应该是什么样子?大小、字体大小、字体、正常粗细、粗体、斜体。所以,网页、表单和结果的所有外观和感觉都编码在 CSS 文件中。这是您可以看到的 HTML 文件的原始代码。你好,欢迎回来。在本模块中,我们将使用 ChatGPT、Google Gemini 和 Hugging Face API 进行一些实践。所以,让我们开始吧。所以,在第一个视频中,我们将使用 Python 中的 JPT 和 Google Gemini 来使用它们的 API 完成一些实际任务。所以,首先我们需要安装 OpenAI。您可以取消注释此行代码并执行。同样,我们需要安装 Google 的生成式 AI 包。让我们看看如何创建访问 ChatGPT 模型所需的 OpenAI 密钥。所以,我们将导航到 OpenAI 登录页面。如果您从未创建过帐户,请创建一个帐户。如果您已经有一个帐户,我们将继续并登录。您可能需要输入发送到您收件箱的验证码。身份验证后,它将带您到 OpenAI 平台页面。您可以看到您创建的不同项目。所以,如果您从未创建过项目,目前就让它成为默认项目。所以,如果您在右上角看到 API 参考。所以,这将让您快速了解 OpenAI API 的工作原理。首先是关于身份验证,如何发出请求,有哪些端点可用于音频、聊天、嵌入、微调、批量请求、文件上传等。所以,所有这些都包含在此 API 参考页面中。所以,请随时探索此文档。然后我们可以导航到仪表板。所以,从左侧的仪表板中,您可以看到您的 API 密钥。所以,如果您从未创建过 API 密钥,此字段将为空。所以我将创建一个新的密钥,点击右上角的按钮。如果您愿意,可以为此密钥提供一个名称。我们称之为 AI Agents。我将创建密钥。请确保您复制它,然后您可以打开一个记事本并安全地保存它。我们将在 Jupyter Notebook 中需要此 API 密钥。所以,保存此文件,然后我们就完成了。所以,让我们回到这里。所以,执行此单元格。它会要求您输入 API 密钥。所以,我们刚刚创建并复制的 API 密钥。我将在此处粘贴并按 Enter。我们将把 OpenAI API 密钥添加到环境变量中。同样,我们还需要创建 Gemini API 凭据。所以,这里有一个链接。您可以通过点击此处获取 API 密钥。所以,您必须先登录您的 Google 帐户。然后从那里,在左上方,您可以看到“获取 API 密钥”按钮。这里您也可以看到“获取 API 密钥”按钮。您可以点击它。如果您从未创建过项目,您将必须先创建一个项目,否则您可以选择一个现有项目,然后在该现有项目中点击 API 密钥。同样,您可以复制此密钥并保存。所以,一旦我们保存了 Google Gemini API 密钥,我们就必须在这里输入它,然后按 Enter。让我们执行此操作。所以我已经将我的 Google API 密钥设置为环境变量,我们可以继续了。所以,我在这里定义了一个函数,它将接受用户提示和模型。我将尝试 GPT-4 模型和 Gemini Pro 模型。Gemini Pro 模型来自 Google,GPT-4o 模型来自 OpenAI。所以,如果模型是 GPT-4o,我们将这样调用 ChatGPT API,我们将这样调用 Google Gemini API。好的。所以,我们需要定义角色和提示。所以,提示将作为用户输入,而实际函数是 `chat.completions.create`。我们将传递模型和消息作为列表。在这里我们也可以设置温度。所以,温度越高,模型响应中的随机性程度就越高。最后,一旦我们将这三个参数传递给聊天完成 API,我们将获得响应,并从响应中提取消息及其内容。所以,这个函数将返回消息的最终响应及其实际内容。现在,如果模型名称是 Gemini Pro,我们将使用 `generative_model` 类,初始化它,然后将用户提示传递给该模型的 `generate_content` 内置函数,并从模型和响应中获取响应。我们有 `text` 字段。所以我将从响应中提取该文本并在此函数调用中返回。如果您提到任何其他模型名称,不同于 GPT-4 或 Gemini Pro,那么此函数将返回此错误消息,基本上说明 LLM 未配置,原因是来自不同供应商的每个模型都有不同的 API 调用方式。所以,没有通用的方法可以调用所有可能的模型。好的。所以,我们需要确定我们正在访问哪个模型。所以,我们将在这个笔记本中进行几个练习。所以,在第一个练习中,我们将使用上面创建的 `chat` 和 `google_get_completion` 函数生成一些文本。这是我正在传递的用户提示,默认情况下模型配置为使用 GPT-4。所以我不需要做任何其他事情。我将执行它。根据您的互联网速度和服务器负载,可能需要几秒钟才能获得服务器响应。所以,写一个关于大学生的短篇故事。我得到了一个关于一个名叫 Lena 的学生的故事,以及她的大学生活。好的。并且从 Gemini Pro 模型获得了类似的响应。好的。所以,这里的用户提示完全相同。模型名称已更改为 Gemini Pro。让我们看看 Google Gemini 会写出什么样的故事。所以,Google Gemini 识别的身份是 Emily Carter。所以,我认为这个故事是关于 Emily Carter 的。您可以花时间阅读这个故事。现在,让我们尝试零样本提示,基本上我们将向模型提出一些问题,并期望得到答复。所以,这个 `display_in_markdown` 函数被导入,以便更美观地显示模型的响应。所以,再次使用 `get_completion` 函数,我将提示设置为“用两个要点解释生成式 AI,非常简短和清晰”。所以,让我们获取响应并以一种好的方式显示该响应。好的。所以,这是我从 GPT-4 模型收到的两个要点。生成式 AI 指的是基于机器学习模型(如神经网络)的算法,这些算法可以创建新的内容,如文本、图像、音乐或代码等。让我们看看 Gemini 模型的回应是什么。我在这里更改了模型名称。所以,Gemini 模型给了我一个更简洁的回应。生成式 AI 是一种可以从头开始创建新数据或内容的 AI,例如生成图像、文本或音乐。完美。所以,我们将在下一个笔记本中尝试更多关于提示的示例,或者基本上使用不同模型的 API。好的。你好,欢迎回来。所以,在这个实践练习中,我们将使用开源大型语言模型进行一些提示工程。您可以使用 Hugging Face Serverless API。基本上,Hugging Face 是各种大型语言模型的存储库。我们可以从 Hugging Face 存储库下载这些模型,或者我们可以直接调用托管在 Hugging Face 服务器上的这些模型。所以,在这个笔记本中,我们将只使用这些模型的推理 API,这些模型已经托管并在 Hugging Face 服务器上运行。在下一个笔记本中,我们将实际下载这些模型,然后本地使用它们。对?所以,在这个笔记本中,我们将学习如何通过 Hugging Face 推理 API 运行任何开源模型,您也可以在 Google Colab 上运行整个笔记本。现在我正在我的本地机器上运行它。所以,Hugging Face 制作了一些称为推理 API 的东西,可以免费使用,但有一些基本的速率限制。所以,根据公平使用政策,如果您不超出速率限制,您可以直接访问托管在 Hugging Face 服务器上的这些模型并直接获得响应。好的。所以,不要过于频繁地尝试访问此 API 并达到速率限制,否则您将被 Hugging Face 阻止。好的。所以,我们将在本笔记本中尝试两个模型。一个是 Mistral 7B Instruct 模型,这是一个 70 亿参数模型,这个 Transformer 模型由法国公司 Mistral AI 构建,它是一个指令微调模型。您可以按照此链接。这是用于指令微调的基础模型。所以,这就是我们所说的模型卡。所以,如果您从未在 Hugging Face 上创建过帐户,您将必须先创建一个帐户。我已经登录了。您可以看到我已经登录到我的 Hugging Face 帐户。好的。第二个模型我们将使用 Gemma 2B IT 模型。它也是指令微调的。所以,这也是 Google 的一个开源模型。它是一个 20 亿参数模型,并且经过微调以进行指令遵循任务,这使我们能够处理各种复杂的自然语言处理任务。好的。所以,当然您需要互联网连接,因为我们将从 Hugging Face 服务器访问 API 调用。您还需要 Hugging Face 帐户和 API 密钥。所以,首先让我们看看如何创建 Hugging Face 密钥。所以,您可以转到此链接,它将带您到帐户页面,您可以在那里获取访问令牌。好的。在左侧,您可以看到访问令牌。所以我已经创建了几个密钥,但让我创建一个新密钥。所以,点击此按钮,将有三个选项:细粒度、读取和写入。对于您将在 Hugging Face 平台上进行的绝大多数任务,您将需要读取令牌类型。这样您就可以对 Hugging Face 上所有公开可用的模型进行 API 调用。所有可用于推理 API 的模型,使用写入权限,您实际上可以上传自己的模型到 Hugging Face 存储库,如果您想这样做的话。在细粒度中,您可以为您的存储库提供细粒度的读取和写入访问权限。所以,我们将使用只读令牌类型,这是您在本课程中最常使用的令牌类型。所以我可以提供一个名字,比如 AI Agents。然后我将提供,所以这是令牌,这是令牌名称,您可以这样说,它对您组织的所有资源具有只读访问权限,并且能够代表您进行推理调用,这正是我们所寻找的。所以我将继续创建令牌。我将得到一个密钥。所以,不要忘记复制它并像保存 OpenAI 访问密钥一样安全地保存它,然后我们将回到笔记本。所以,这里,让我们执行此操作。您将被要求粘贴该密钥并按 Enter。所以,我们将使用 `requests` 库来向 Hugging Face Serverless API 进行推理 API 调用。所以,首先我们需要创建标头,就像我们在上一个模块中所做的那样,然后我们将创建 `payload` 和模型 API URL 作为查询函数的输入。所以,这个用户定义的 `query` 函数将接收 `payload` 和我们想要调用的模型 API。好的。所以,我们正在向此模型 API URL 发送一个 `POST` 请求。所以,不同的模型将有不同的 API URL,我们还将传递标头,其中包含我的身份验证令牌,我们将定义一个 JSON 负载。最后,我们将从服务器获取响应,在 `POST` 请求完成后,然后从那里访问响应的 JSON 部分。所以,让我创建这个函数。所以,有很多设置,您可以通过点击此链接找到详细文档。但是,我们最常需要并且您应该知道的配置是,我们可以限制模型创建特定的令牌限制。所以,如果您在这里给出一个 `max_new_tokens` 值,比如 200 或 500。所以,模型将最多创建这么多令牌。好的。所以,这是您希望模型在响应中创建的令牌数量。温度再次,值通常在 0 到 1 之间。所以,值接近 0 表示响应更确定。每次调用模型 API 时都会获得相同的响应。所以,创造力会更少,模型的响应会更现实,幻觉也会更少。然而,如果温度值设置为更高,接近 1,那么模型的响应将更具创造性,并且您允许响应有更多变化。在这里,我正在创建 API URL。所以,您可以在页面上找到此 API URL。所以,这是模型卡页面。这就是我们所说的模型卡页面。右侧有一个按钮,上面写着“使用此模型”。所以,通过使用 Transformer API。所以,一旦您点击它,它将为您提供一个简短的代码,您可以复制并开始使用。所以,这里您可以看到这是模型链接。但是,现在我们将直接使用模型 API URL。好的。所以,让我们执行此操作。同样,这是我们将使用的 Gemma 2B IT 模型的 API URL。所以,有一些标准参数。例如,等待模型的响应。是的。并且,我们不想返回完整的文本。我们想要返回的最大令牌数是 1000,等等。所以,让我们开始提示我们的模型。首先,我们将进行基本的问答。这是对模型的零样本提示。所以,这里我传递给模型的提示是“你能向五年级学生解释什么是量子计算吗?”。所以,这是完整的提示。让我打印提示,这是模型的 API URL。好的。并且,当您运行此代码时,您将获得模型的响应。所以,我在这里传递 Mistral 模型的参数,我使用的模型 API URL 是 Mistral 的。所以,基本上这个响应是从 Mistral 模型获得的。现在,可能出现错误的可能性。所以,如果您收到错误,最可能的原因是您必须接受许可。所以,点击此链接。它将带您到模型卡页面。并且,您可能会在这里看到一个接受窗口。所以,由于我已经接受了,我已经获得了访问此模型的权限。所以,这是一个受限模型。所以,您必须接受此模型的许可协议。是的。所以,例如,如果我点击 Gemma 2B IT,这是您第一次访问 Mistral 模型时会看到的窗口。所以,一旦我确认许可,我将获得访问此模型的权限。所以,让我授权此模型。所以,这是一次性活动。所以,这个模型现在将可供您的帐户访问。所以,再次消息说您已获得访问此模型的权限。所以,这是一次性活动,您可能需要为少数受限模型执行此操作,而不是非常自由地公开访问。所以,回到这里,既然我们已经获得了访问模型的权限,我们就可以开始查询该模型了。所以,我得到了 Mistral 模型的回应。现在,让我们看看 Gemini 模型类似的响应。所以,这是响应代码。200 表示成功检索到模型的响应。所以,这不是错误。200 基本上是成功消息。所以,提示仍然是相同的,即“你能向五年级学生解释什么是量子计算吗?”。所以,这次 Gemini 模型回复说,想象你有一个硬币,普通硬币有两面,正面和反面,但这是一个特殊的硬币,叫做量子硬币,它可以同时有正面和反面,我的意思是,对吧?所以,如果您想美化您的响应,您可以使用 IPython 显示中的 `display` 和 `markdown` 函数。所以,这稍微好一些。好的。让我再举一个例子。我这里有一大段文字,您可以说是一个报告。在这种情况下,我正在创建一个提示模板。在这种情况下,提示模板说“总结以下报告,用三个反引号分隔,关于生成式 AI,最多五行”。所以,基本上,我将此报告作为占位符传递。所以,这份报告将与此提示一起发送。这份报告将与此提示一起发送。并且,我要求生成式 AI 模型最多用五行进行总结。好的。所以,让我们先打印提示,您可以看到提示,报告与指令一起发送。好的。所以,这是您传递给模型的完整提示。现在,再次使用相同的函数。所以,这里的 `payload` 是我创建的整个提示,我这次将使用 Mistral 模型,我将从 Mistral 模型响应中检索生成的文本,然后显示它。好的。所以,我的 Mistral 模型说,生成式 AI 是一项技术,它可以……所以,这是整个文本的摘要版本。好的。如果您愿意,可以数一下,不应超过五行。同样,对于 Gemini 模型,唯一的区别是使用了 Gemma 2B IT API URL,而不是 Mistral 模型。让我们看看这里的响应。我这里只有一行响应。好的。不符合预期。这至少应该是五行,就像这样。无论如何,让我们再举一个例子。我这里有一篇评论,关于,所以,这里的评论说,“我最近与一家房地产公司合作购买了我的第一套房子,体验非常出色。”所以,代理知识渊博、耐心、反应迅速等等。他们指导我完成了整个过程,这本可能是一次压力很大的经历。所以,基本上,这是对一家房地产公司的评论。好的。所以,扮演一名客户评论分析师,并根据以下客户评论文本执行以下任务。所以,首先,我要求模型找出情绪,正面、负面或中性。然后,我要求模型从评论中提取五个关键主题或短语。好的。然后,再次将整个评论文本作为占位符传递,就像我们在上面的情况一样,再次使用相同的查询函数,这次我将首先使用 Mistral 模型,让我获取 Mistral 模型的回应并查看。好的。所以,整体情绪,模型确定为正面,这些是评论中讨论的五个关键主题或短语,所以,出色的体验,知识渊博的代理,耐心的,顺畅愉快的体验,过程和指导。完美。让我们看看 Gemini 模型会说什么。同样,唯一的缺点是房产价格过高。总的来说,我会给我的体验打四星或五星。是的。好的。整体情绪是积极的。就是这样。并且,客户似乎对这次体验表示满意。这些是五个关键主题。所以,这是一个完成。如果您注意到,这是我从 Gemini 模型获得的完成。好的。所以,Gemini 模型认为之前的响应不完整。所以,它首先完成了那个响应,不是响应,而是评论。所以,评论首先被完成,虽然这并不符合预期,但评论被完成,然后进一步提取了情绪和关键主题。好的。完美。你好,欢迎回来。所以,在这个笔记本中,我们将看到如何使用 Hugging Face 存储库下载开源大型语言模型。所以我强烈建议您在具有 GPU 访问权限的机器上运行此模型。如果您的本地笔记本电脑没有 GPU 访问权限,您可以将此笔记本上传到 Google Colab,我们可以使用 Google Colab 提供的免费 GPU。好的。所以,这是我们将再次使用的模型。所以,如何在 Google Colab 上打开这个笔记本?所以,让我们先去 Google Colab。所以,colab.research.google.com。您可能需要先登录您的 Google 帐户。所以我已经登录了。然后从这里您可以上传此笔记本。所以我已经在我的本地机器上有了这个笔记本。所以,这是我上传到 Google Colab 的第三个笔记本。我想在 Google Colab 上运行那个笔记本。好的。所以,这是模型。所以,在这里我们成功地将我们的 Jupyter Notebook 上传到了 Google Colab。我们将再次使用 Gemma 2B,一个 20 亿参数模型,它是 Google 的 Gemma 20 亿 LLM 模型上的指令微调。这是基础模型,这是指令微调模型。Recurrent Gemma 是一个开源语言模型系列,它构建在 Google 开发的 Recurrent 架构之上,这个模型经过预训练,后来也经过指令微调,以遵循英语的自然语言指令。首先,在右上角,您必须先选择一个内核。所以我强烈建议您选择 GPU 内核。所以,连接到托管运行时。在这种情况下,它是 T4。所以,您可以通过点击“更改运行时类型”看到所有可用的运行时类型。您可以将硬件加速器设置为 T4 GPU。所以,确保您使用的是 T4 GPU,然后点击保存。保存后,点击连接按钮,等待几秒钟,直到您的 Colab 笔记本连接到 Google 的 GPU 服务器。所以,一个服务器已被分配,现在我已被分配了 GPU。所以,您可以看到我们大约有 13 GB 的 RAM 可用,以及大约 112 GB 的磁盘空间。所以,我们需要至少 5 GB 的 GPU 内存。所以,这应该足以运行 Recurrent Gemma 的推理。好的。所以,这个将被下载的模型,它将占用大约 5 GB 的 GPU 内存。好的。所以,让我们继续。所以。
如果您在 Google Colab、任何有 GPU 的服务器或本地机器上运行此代码,那么只有您运行此代码。否则,这将引发错误。因此,由于我已经连接到 GPU,我可以运行此代码。它会检查可用的 GPU 内存。当前有多少 GPU 内存可用。它显示目前我的 GPU 内存上没有任何进程。因此利用率也为 0%。如果您看到目前我拥有的是 Nvidia 版本号,即 GPU 中安装的驱动程序版本。GPU 将支持 CUDA 语言。所以这是我 GPU 上可用的 CUDA 版本。已分配给 GPU 的某个名称,以及其他等等。好的。所以主要的是这里的内存使用情况。您可以看到目前几乎为零 MB,因为我们还没有开始使用它。嗯,您可能需要安装 transformers 库。所以让我们继续这样做。使用 hugging face 创建的 see transformers 库。所以如果您想使用 hugging face,您将不得不安装 transformers 库。好的。我现在已经安装了它,让我们继续。您可能需要重新启动运行时以确保所有已安装的库都已准备就绪。好的,让我们这样做。点击运行时并重新启动会话。好的,点击是。等待几秒钟。我认为已经完成了。所以我们可以再次检查 Nvidia SMI。好的,这看起来不错。现在我们可以再次开始导入 hugging face API 密钥。所以当我运行此代码时,它会要求我登录。所以我正在 hugging face 上注册这个 Jupyter notebook。它要求我提供令牌。所以您必须粘贴我们之前创建的 hugging face 令牌。所以您可以取消选中此项并点击登录。登录成功。所以我现在可以从这个在 Colab 上运行的 Jupyter notebook 访问 hugging face。这是模型 ID。您可以通过点击此链接来查看模型 ID 卡。这是模型卡。好的。以及如何使用此模型?说明在右上角,使用 transformers 库。所以一些基本代码已经作为入门代码提供。好的。所以如何将其用作管道以及如何调用它?所以一切都作为入门代码在那里。所以我们将回到我们的 Colab 并运行它。所以您可以看到,整个模型现在正在下载到 Google Colab 中。所以过程仍在进行中。您可以看到模型正在下载时,它还会下载许多其他内容,例如分词器配置。这是分词器模型。现在这个分词器模型是 4.2 MB。分词器 dojson 文件。所以它包含所有分词器信息。如果您在此 JSON 文件中有一些特殊分词器信息,然后还有其他配置。所以主要的是这个模型本身。您可以看到 safe tensors 对应于此模型的权重。所以基本上您正在下载的是模型权重,大约为 4.97 GB。好的。所以我的模型已下载到 Google Colab 服务器。您可以看到已经消耗了近 5.5 GB 的空间。所以让我们尝试一些基本提示。所以首先我必须创建一个消息。所以将用户设置为角色,将内容设置为实际提示。所以我将提示我的模型用三个要点解释什么是 AI。所以这是我从分词器中的 apply chat template 函数传递的聊天,它将对提示进行分词并打印提示。好的。所以基本上我正在做的是这个提示是如何被模型解释的。好的。所以 BOS 基本上是句子的开头。而这些是特殊标签,您可以说它们被传递给模型,以便模型知道什么是系统消息,什么是用户的实际提示。好的。所以这些都可以称为系统消息。这些是标签,用于此的特殊标签。而在用户内部,这就是实际提示所在的位置,对吧?所以让我们看看模型 do device。这应该给我 CUDA 索引零。所以 CUDA 指的是 GPU。所以现在我的模型已挂载到 GPU。嗯,让我们对这个提示进行编码。所以当提示被编码时,它基本上会给出分词 ID,而这些分词 ID 被模型用作输入来生成输出,对吧?所以输入和输出本质上将是分词 ID,对吧?现在我正在使用输出分词 ID 来解码这些分词 ID 中的实际英文单词。所以分词 ID 本质上是数字。我正在使用 decode 函数将其转换回英文,您可以说,对吧?所以这是从分词器解码的输出。所以这是最终输出,您可以说,对吧?所以人工智能是……的能力,等等。所以如果这看起来有点复杂和令人不知所措,那么这就是 hugging face 提供管道的原因,您可以更轻松地使用它。好的。而这个管道就是您也可以从模型卡页面看到的。所以我将给您一些关于如何使用该管道的示例。所以管道使其变得容易。我们不必去分词器输入输出解码函数等等。事实上,每个模型都有自动分词器,它们可以轻松地隐式处理这些任务。好的。所以再次,我们已经在之前的视频中讨论了这些参数。所以温度控制着模型的创造力。接近零的值意味着更确定性,更少创造性。接近一的值意味着您允许模型更具创造性,这意味着当您多次重新运行相同的代码时,预期输出会有更多变化。对吧?所以在这里我正在使用 model.generate 生成函数来实际生成响应并获取输出。但再次,输出是分词 ID 的格式。使用这些分词 ID,我正在解码并生成英文文本。所以这是相同的事情。好的。所以管道使发送提示更容易。所以您不必每次都进行编码和解码。这就是这里的主要价值主张。所以 transformer.pipeline 管道在这里您可以使用文本生成端点,您可以说。每个模型将有不同的端点用于不同的任务。我正在使用文本生成端点。我正在传递模型 URL 或推理 API URL 和分词器信息。所以这里的分词器是我们导入的。所以所有这些分词器信息我们都传递在这里,并将其映射到 CUDA。所以基本上这个模型推理任务将在 CUDA 上运行。好的,我已经创建了这个管道。我再次打印我的提示,它将是这个。然后让我们将这个提示传递给管道并直接生成响应。好的,我将最大分词数限制为 150,并且我允许稍微平衡的响应。所以这是我收到的响应。这是完整的响应。好的。而我必须从中提取生成的文本部分。好的。所以让我打印提取的生成文本。所以它是这样出现的。如果您想要更漂亮的响应输出,您可以再次从 ipython 导入 display 和 markdown 函数。使用 markdown 函数以 markdown 格式打印它。好的。是的。所以这看起来好多了。现在让我们看看 GPU 已经使用了多少。所以如果您看到这里已经使用了 5.4 GB 的内存。所以它使用了超过 5 GB 的内存。这正是我们在笔记本开头提到的。好的。所以您也可以打印管道。我将在这里再举几个例子。在这个例子中,我们将再次对模型进行零样本问答。所以我们将向本地加载的 LLM 传递一个提示,并要求它通过提示执行一些 NLP 任务。所以提示文本将是用户的输入。其余是默认系统默认。嗯,好的。所以这里的用户提示是你能解释一下什么是 mod gauge 吗?所以这作为输入。所以这个输入将被映射到内容部分,而整个载荷将被传递给分词器中的 apply chat template 函数。好的。让我们看看这个提示。所以这是我从分词器那里得到的完整提示。而分词后的提示现在被交给管道来生成输出。所以生成的输出文本就是我现在将要打印的。好的。所以这是我收到的完整响应。有很多信息。所以我们可以以正确的格式显示它吗?所以我再次使用 markdown 函数以 markdown 格式显示它。您可以看到现在它格式非常好,而且更容易阅读。我还有另一个例子,我将分享一份关于生成式 AI 的详细报告,并要求模型对其进行总结。好的。所以这是我正在创建的一种提示模板。所以在这个提示模板中,我将附加这份报告。这是我将附加在这份提示模板中的整个报告。好的。所以创建 jam prompt。这是完整的提示文本,而这个提示文本就是我将传递给管道的整个提示模板。所以让我们这次看看。所以最大分词数是 500。所以我预计摘要将小于或等于 500 个分词。所以让我打印它。好的,完美。所以我得到了正好五行。这正是我要求的。所以给我一个正好五行的摘要。所以我得到了这个整个文本的五行摘要。完美。如果您愿意,我可以格式化它。所以这里的这些破折号变成了项目符号。最后一个例子。我们将把它用于基本的感情分析。所以这里我有一些评论,我将把这些评论附加到这个提示模板上。所以这个提示模板做什么?它要求模型充当客户评论分析师,并要求模型执行两项任务。一是找出整个评论的感情,二是提取五个关键主题。整个提示模板现在被作为提示传递。所以这将给我一个分词后的提示,而这个分词后的提示将进入管道,最终生成输出。好的。所以让我显示这个响应。所以总体感情似乎是积极的。让我们阅读评论。我最近与这家房地产公司合作,等等。这次经历非常出色,知识渊博,耐心,指导我完成了每一步。是的。所以这绝对看起来是相当积极的回应。评论者表达了满意,而这些是关键短语。所以我可以美化它并显示吗?完美。所以这是一个相当美化的显示。所以这就是关于在本地机器上使用大型语言模型的编码实践教程,通过从 hugging face 存储库下载。您好,欢迎回来。随着人工智能的发展,旨在帮助我们构建更先进、更自主系统的框架和工具也随之发展。现在,我们不必从头开始,而是拥有强大的工具,可以更轻松地创建、管理和部署 AI 代理。我将在本视频中向您介绍其中一些工具。这些工具将在本课程的后续课程中更全面地使用。在本节中,我们将探讨 AI 开发中的四个关键工具。Langchain、Langraph、Creai 和 Autogen。我们将讨论每个工具最擅长什么,一些实际用例,以及进行比较以帮助您决定哪个可能适合您的需求。让我们开始吧。但首先,为什么我们需要专门的工具来构建 AI 代理?嗯,让我们考虑一些挑战。首先,构建这些代理很复杂。其次,集成可能是一个真正的挑战。每个代理可能需要从多个来源提取数据,与不同的系统交互,并与其他模型良好协作。第三,可扩展性。随着您的代理功能不断增强,它需要处理更多任务、更多用户,并且在扩展时通常需要保持一致的性能。那么解决方案是什么?我们谈论的是能够理解语言、做出决策甚至采取行动的 AI。所以有很多事情需要处理,尤其是当您想快速开发一些东西并使其灵活时。这些工具使流程更加顺畅,并有助于将所有内容集成到单个工作流程中。Langchain 和 Autogen 等工具简化了所有这些任务,减少了开发时间和复杂性。让我们看看这些工具各自带来了什么。让我们从 Langchain 开始。Nin 是一个开源框架,已成为使用 OpenAI 的 Chat GPD 等大型语言模型的开发者的首选。它旨在简化使用这些模型构建应用程序的整个过程。是什么让 Langchain 与众不同?首先,它具有广泛的集成。此工具与从 Amazon 和 Google 等云存储提供商到 API 和网页抓取工具的一切都兼容。因此,它可以从几乎任何地方收集信息。另一个突出特点是其文档处理能力。Langchain 可以处理 50 多种文档类型,这对于需要处理大量不同数据的应用程序非常有帮助。LChain 拥有强大的编码和调试工具,使开发人员更容易在出现问题时找到并修复它们。此外,它还包括内置的内存功能,无论是短期记忆还是长期记忆。Langchain 让代理能够记住重要的细节,跨越交互,帮助它们保持相关性和上下文感知。让我们看看您可能使用 lang 的一些具体方式。Langchain 在几个特定应用程序方面表现出色。聊天机器人是最受欢迎的之一。Slankchain 帮助开发人员创建可以回答问题、进行对话并从多个来源检索信息的聊天机器人,从而提供更具活力和响应性的体验。React 代理是一种智能系统,旨在结合推理和行动,使其能够动态地适应和响应复杂环境。通过将规划与实时反馈相结合,React 代理可以在不确定的环境中高效地解决问题并改进决策过程。对于软件开发人员来说,Langchen 还可以帮助进行代码分析。开发人员可以使用它来生成、分析甚至调试代码。这就像拥有一个理解代码并能提出建议的 AI 助手。接下来是 Langraph。另一个与 lang chain 有点不同的工具。Lang graph 专注于工作流管理。它允许您使用称为有向无环图或 DAG 的东西来设计工作流,其中工作流的每个部分都由一个节点表示。Langraph 的真正酷之处在于其高级内存功能。它不仅可以记住重要的细节,还可以处理错误,甚至在需要时允许人工干预。这使其非常健壮,非常适合更复杂的项目。另一个独特的功能是 Langraph 与 Langchain 无缝集成。因此,您可以获得两全其美,即 Langchain 的资源和 Langraph 的工作流结构。最后,Langraph 具有缓存功能。因此,您可以保存工作流的进度并在以后返回到它,这对于复杂的应用程序来说非常有用。那么您会在哪里使用 Langraph?它非常适合管理具有多个需要相互交互的步骤的复杂工作流。想象一个数据处理管道,其中一个步骤依赖于另一个步骤的输出。Langraph 可以处理所有这些,同时保持一切井井有条。Agentic rags 将生成模型与推理能力相结合,使代理能够根据学习到的知识和逻辑推理自主生成响应。因此,在多代理系统中,多个此类代理会进行协作或竞争,共享信息,协调行动,并通过集体推理和通信解决复杂任务,从而增强动态环境中的可扩展性和适应性。所有这些都可以由 langraph 非常轻松高效地处理。接下来是 Crew AI。Crew AI 采用了一种独特的方法,围绕特定角色组织 AI 代理。这意味着每个代理都被分配到一个特定的角色或功能,从而可以轻松地设计多个代理协同工作的系统。Crew AI 的独特功能之一是动态任务分配。代理可以根据需要自主地将任务分配给彼此,这对于需要实时决策的项目来说非常完美。Crew AI 也建立在 Lang Chain 之上,这使其能够访问 Langchain 的所有集成和工具。如果您是喜欢监控和跟踪的开发人员,Crew AI 会提供有关每个代理性能和任务进度的详细见解。KUI 在创建多代理研究团队方面非常出色。您可以构建协作分析数据、进行实验和报告发现的代理。基本上自动化了大部分研究过程。在客户支持方面,Crew AI 的代理可以与客户互动,回答问题,甚至在需要时将问题升级给人工代理。这为更复杂的案例腾出了人力资源。它也是教育的理想解决方案。想象一下个性化学习代理,它们可以适应学生的进度并提供量身定制的反馈。最后,Cre AI 可以在软件开发中提供帮助,协助进行编码任务、调试甚至测试应用程序。现在,让我们谈谈 Autogen,微软的对话代理工具。Autogen 之所以脱颖而出,是因为它将工作流视为对话。这使得它非常直观,特别是对于任何熟悉聊天机器人或其他交互式系统的人来说。Autogen 的模块化设计意味着您可以通过添加新组件和工作流轻松扩展其功能。您甚至可以使用这些工作流执行代码,增加了很大的灵活性。它还支持跨语言操作和异步消息传递,如果您正在构建一个需要代理独立运行并根据需要进行通信的分布式系统,这是理想的选择。它还支持跨语言操作和异步消息传递,如果您正在构建一个需要代理独立运行并根据需要进行通信的分布式系统,这是理想的选择。Autogen 还具有高级功能。它支持容器化代码执行,这意味着代理可以在隔离的环境中编写和运行代码。这对于安全性和灵活性来说非常棒。它还支持多种编程语言,目前支持 Python 和 .NET,并且有更多语言正在开发中。如果您正在处理一个大型项目,异步消息传递允许代理在不等待的情况下进行通信,这对于可扩展的分布式系统来说是理想的选择。总而言之,Langchain、Langraph、Creai 和 Autogen 各自提供不同的功能和能力,适合不同类型的项目。感谢您的参与,希望本节能让您清楚地了解使用这些工具的可能性。