《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
发布时间:2026/10/14 3:24:57 锦皓数字建站

《计算机是如何工作的人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9第 8 章研究了软件的基础在处理器上运行的机器码以及汇编语言一种人类可读的机器码表示。尽管所有的软件最终都必须转换成机器码的形式但绝大多数软件开发人员都用更高、更抽象的语言编写程序。本章将介绍高级编程。我们将概述高级编程讨论各种编程语言中的常见元素并研究几个示例程序。9.1 高级编程概述虽然可以用汇编语言甚至可以用机器码编写软件但这既费时又容易出错并且会使软件难以维护。此外汇编语言是特定于 CPU 架构的所以如果汇编语言开发人员想要在其他类型的 CPU 上运行其程序就必须重新编写代码。为了克服这些缺点人们开发了高级编程语言这就允许程序用独立于特定 CPU 的语言来编写并且它们在语法上更接近人类语言。许多语言都需要编译器——一种把高级程序语句转换为特定处理器机器码的程序。使用高级编程语言软件开发人员可以编写程序一次然后针对不同类型的处理器进行编译有时只需对源代码进行少量修改甚至不用修改。编译器的输出是一个目标文件它包含了针对特定处理器的机器码。另一种被称为链接器的程序用于把一个或多个目标文件转换成一个可执行文件这样操作系统就可以运行这个可执行文件了。链接器还可以在需要的时候引入其他已编译代码库。编译和链接过程如图 9-1 所示。图 9-1 从源代码构建可执行文件编译和链接的过程被称为打包。但是在常见的用法中软件开发人员在说到编译代码时其实际意思是指包含编译、链接和任何其他把代码转换成最终形式所需步骤的完整过程。编译器通常会自动调用链接步骤使其对软件开发人员的可见度降低。9.2 C 和 Python 简介学习高级编程最好的方法是研究编程语言并用这些语言编写一些程序。本章选择两种高级语言C 和 Python。这两种语言都很强大也很有用下面用它们来演示编程语言如何用不同的方式来提供类似的功能。我们先对它们进行简要介绍。C 编程语言可追溯到 20 世纪 70 年代早期当时它被用于编写 UNIX 操作系统的一个版本。尽管 C 是一种高级语言但它与底层机器码离得并不远这使得它成为操作系统开发或其他直接与硬件交互的软件开发的绝佳选择。20 世纪 80 年代出现了 C 的升级版称为 C。C 和 C 是功能强大的语言几乎可以用来完成所有事情。然而这些语言很复杂且没有提供很多防止程序员错误的保护措施。对于需要与硬件交互的程序以及那些要求高性能的程序比如游戏来说它们仍然是主流的选择。C 对于教育目的也很有用它提供了底层概念与高级概念之间的直接映射这就是本章选择它的原因。与 C 相比Python 编程语言离底层硬件更远。Python 最早是在 20 世纪 90 年代发布的历经多年越来越受欢迎。它以易读且对初学者友好而闻名同时它还能提供支持复杂软件设计所需的一切。Python 有 “自带电池” 的理念意思是 Python 的标准发行版包含了有用的功能库开发人员能轻松地将其用于程序设计中。Python 的直接属性使其成为教授编程概念的上佳选择。现在我们来看看大多数高级编程语言中都有的元素。我们的目标不是把你教成特定语言的程序员而是让你熟悉编程语言中常见的思想。请记住高级编程语言中的功能是 CPU 指令的抽象。如你所知CPU 提供访问内存、逻辑运算和控制程序流的指令。让我们来看看高级语言如何揭开这些底层功能。9.3 注释我们先介绍编程语言的一个特性这个特性实际上并不会指示 CPU 做事情。几乎所有的编程语言都支持在代码中添加注释。注释是源代码中对代码解读的文本。注释是给其他开发人员看的通常会被编译器忽略它们对编译的软件没有任何影响。在 C 编程语言中添加注释的方式如下所示Python 用 # 表示注释如下所示Python 不支持多行注释程序员只需一行接一行地使用多个单行注释即可。9.4 变量内存访问是处理器的基本功能因此它也是高级语言的必备功能。编程语言访问内存的最基本方式是通过变量。变量是一个确定的内存地址。变量允许程序员给内存地址或内存地址范围指定一个 “名字”然后通过这个名字访问对应地址的数据。在大多数编程语言中变量都有 “类型”以说明它们所保存数据的种类。例如一个变量可能是整数类型或文本字符串类型的。变量也有一个 “值”它是存储在内存中数据。变量还有一个 “地址”尽管这通常对程序员而言是隐藏的这个地址是变量值在内存中的存储位置。最后变量有 “作用域”意思是只有在程序的某些部分即作用域才能访问它们。9.4.1 C 中的变量我们来看一个 C 编程语言变量的例子这段代码声明了一个变量变量名为 points类型是 int在 C 语言中这表示该变量保存整数。该变量被分配了一个值即 27。当运行代码时十进制数 27 被保存到某个内存地址不过开发人员不用操心存储这个变量的具体地址。当前大多数 C 编译器把 int 视为32位的数因此在运行时程序执行的时间为这个变量分配 4 个字节(4B×8bit/B32bit)而变量的内存地址指的就是第一个字节的地址。现在声明第二个变量并为其赋值然后看看这两个变量是如何分配内存的。// Two variables in Cintpoints27;intyear2020;我们先后声明了两个变量points 和 year。它们都是整数所以每个变量都需要 4 个字节的存储空间。变量在内存中的存储方式如表 9-1 所示。表 9-1 变量在内存中的存储方式表 9-1 中使用的内存地址只是例子实际地址随硬件、操作系统、编译器等不同而不同。注意地址增幅为 4因为存储的是 4 字节整数。已知变量前后的地址都用问号表示变量名和变量值因为根据前面的代码我们并不知道存储在那里的是什么。如同 “变量” 这个名字所暗示的变量的值是可以变化的。在前面的 C 程序中如果需要把 points 设置为其他值我们只需简单地在后面的程序中这样写// Setting a new points value in Cpoints31;请注意与前面的 C 代码片段不同这行代码没有在变量名的前面指定 int 类型或任何其他类型。我们只需要在最初声明变量时指定类型即可。在这个例子中变量已经在前面声明过了所以这里只需给它赋值即可。不过C语言要求变量类型保持不变因此一旦 points 被声明为 int那么就只能为它赋整数值。如果试图赋其他类型的值比如文本字符串就会在代码编译时出错。9.4.2 Python中的变量并不是所有的语言都要求声明类型。例如Python 就可以像下面这样声明并赋值变量age22在这个例子中Python 可识别出数据类型为整数因此程序员不用指定类型。与 C 语言不同变量类型可以随着时间变化所以下列语句在 Python 中是有效的age22agetwenty-two让我们仔细看看在这个例子中实际发生了什么。Python 变量没有类型但赋给它的值是有类型的。这是一个重要的区别类型与值相关联而不是与变量相关联。Python 变量可以引用任何类型的值。当变量被分配新值时并不是变量的类型真的发生了变化而是变量绑定了不同类型的值。C 语言则与此相反C 语言变量自身有类型且只能保存该类型的值。这个差异解释了为什么 Python 中的变量可以被赋予不同类型的值而 C 中的变量则不可以。9.5 栈和堆当程序员使用高级语言访问内存时后台管理内存的细节是模糊的具体取决于使用的编程语言。像 Python 这样的编程语言会让程序员几乎看不到内存分配的细节而像 C 这样的语言则会暴露一些底层的内存管理机制。不管这些细节是否暴露给程序员程序通常使用两种类型的内存栈和堆。9.5.1 栈栈 (stack) 是内存的一个区域其运行模型为后进先出 (Last-In First-OutLIFO)。也就是说最后入栈的项是最先出栈的。你可以把栈想象成一叠盘子。当你往这一叠盘子上放新盘子时新的盘子是放在顶部的。当要从这个栈上取盘子时最先拿掉的是顶部的盘子。这并不是说栈中的内容只能按 LIFO 顺序访问读或修改。实际上当前栈中的任何项在任何时候都可以被读取和修改。但是当从栈中移除不需要的项时它们会以从上到下的顺序被丢弃也就是说最后入栈的项会最先被删除。保存栈顶值的内存地址存储在 “栈指针” 处理器寄存器中。当向栈顶添加一个值时会调整栈指针的值以增加栈的大小为新值腾出空间。当从栈顶移除一个值时也会调整栈指针的值以减小栈的大小。编译器生成的代码利用栈来跟踪程序执行的状态以及保存局部变量。这个机制对高级语言程序员是透明的。图 9-2 展示了 C 程序是如何使用栈来保存之前在表 9-1 中介绍的两个局部变量的。图 9-2 栈用于保存 C 语言程序中的变量值在图 9-2 中首先声明 points 变量并为其赋值 27这个值保存在栈中。接下来声明了 year 变量并为其赋值 2020。在栈中第二个值位于前一个值 “之上”。其他值将继续添加到栈顶直到不再需要它们此时会将它们从栈中移除。请记住图中的每个长条只表示内存中的一个已经分配了内存地址的位置虽然图中没有显示这些地址。你可能会惊讶地发现在许多架构中分配给栈的内存地址实际上会随着栈增长而减少。在本例中这就意味着 year 变量的地址低于 points 变量的地址。栈的访问速度很快非常适合用于有限范围的小容量内存分配。独立的栈可供程序的每个执行线程使用。我们将在第 10 章详细地讨论线程但现在你可以把线程看作程序中的并行任务。栈是有限资源分配给栈的内存是有限的。在栈中存放过多的值会导致被称为 “栈溢出” 的故障。9.5.2 堆栈的作用是存放只需临时使用的小值。对于较大的或需要持续较长时间的内存分配更适合使用堆 (heap)。堆是程序可用的内存池。和栈不同堆不采用 LIFO 模型如何分配堆内存并没有标准模型。栈是特定于线程的而程序的任何线程都可以访问堆。程序从堆中分配内存并且这个内存的使用会一直持续直到它被程序释放或者程序结束。释放内存分配的意思就是把它释放回可用内存池。当分配的内存不再被引用时有些编程语言会自动释放堆内存执行这个操作的一种常见方法被称为 “垃圾回收”。其他编程语言比如 C 语言则需要程序员编写代码来释放堆内存。当程序不再使用某块动态分配的内存却没有释放它就会发生内存泄漏。在 C 编程语言中用一种被称为指针的特殊变量来跟踪内存分配。指针就是一种保存内存地址的变量。指针值内存地址可以存储在栈内的局部变量中这个值可以指向堆中的位置如图 9-3 所示。图 9-3 名为 data 的指针变量在栈内它指向堆中的一个地址图 9-3 中的代码片段声明了一个名为 data 的变量。这个变量的类型是 void意思是它是一个指向内存地址的指针用表示这个内存地址可以保存任何类型的数据void 的含义是未指定类型。由于 data 是局部变量因此它在栈上分配。下一行代码调用了 malloc它是 C 语言中的一个函数用于从堆中分配内存。程序正在申请 512B 的内存malloc 函数返回新分配内存中第一个字节的地址。该地址存储在栈内的 data 变量中。我们最终得到了一个局部变量它在栈内的某个地址处这个变量保存的是从堆中分配的地址。9.6 算术运算由于处理器提供了执行算术运算的指令因此高级语言也提供。汇编语言需要特定命名的指令例如 ARM 处理器上用于减法运算的 subs 指令进行算术运算不同于汇编语言高级语言通常包含表示常见算术运算的符号因此在代码中执行算术运算就变得简单了。包括 C 和 Python 在内的大量编程语言使用相同的运算符进行加减乘除运算如表 9-2 所示。表 9-2 常用算术运算符运算运算符加减-乘*除/跨多种编程语言的另一个常见约定是用等于符号 () 表示赋值而不是表示相等。也就是说形如 x5 的语句表示把 x 的值设置为 5。因此可以用自然的方式为算术运算的结果变量赋值就如下列语句一样costpricetax;costpricetax到目前为止我们的重点在于整数运算这在计算中很常见。但是计算机和高级语言还支持所谓的浮点运算。与整数不同浮点值可以表示小数。有些编程语言隐藏了这方面的细节但是在内部CPU 对浮点运算和整数运算采用了不同的指令。在 C 语言中浮点变量用浮点类型比如 float 和 double声明如下所示doubleprice1.99;Python 可以推断变量的类型所以整数和浮点值都以同样的方式进行声明year2020price1.99整数与浮点数之间的差异有时会导致意想不到的结果。举个例子假设有如下 C 代码intx5;inty2;intzx/y;你预期的 z 值是多少事实证明由于涉及的所有数都是整数因此 z 的最终值是2不是 2.5。作为整数z 不能保存小数数值。现在我们稍微修改一下代码如下所示intx5;inty2;floatzx/y;注意z 现在的类型是 float。你现在预期的 z 值是多少有意思的是z 现在等于 2.0仍然不是 2.5这是因为除法运算发生在两个整数之间所以其结果也是整数。除法运算结果是 2当它被赋值给浮点变量 z 时其值为 2.0。C 语言是很确切的它被编译成与程序员所述非常相似的指令。这对于那些想要精确控制任务处理的程序员来说非常棒但对于那些 希望从其编程语言中 获得更直观行为的 程序员来说 就不总是那么好了。Python 试图变得更有用自动分配类型以允许在这种情况下获得小数结果。如果我们用 Python 编写与之等效的代码z 中保存的结果将为 2.5。x5;y2;zx/y;有些语言提供算术运算符用缩写方式表示运算。例如C 语言提供了递增加 1和递减减 1运算符如下所示xx1;x;x--;注意有趣的是编程语言 C 的名字意在传递一种想法即它是对 C 编程语言的改进。Python 还为算术运算提供一些快捷运算符。 和 - 运算符允许程序员对变量进行加减运算例如catscats3;# 等同于cats3; 和 - 运算符在 C 语言中也可以使用。9.7 逻辑运算如前所述处理器非常善于执行逻辑运算因为逻辑是数字电路的基础。编程语言也提供了逻辑处理功能。绝大多数高级语言提供两种类型的运算符来处理逻辑运算按位运算符和布尔运算符。前者处理整数的位后者处理布尔真/假值。这里的术语可能会令人困惑因为不同的编程语言使用不同的术语。Python 用 “按位” 和 “布尔” 描述C 用 “按位” 和 “逻辑” 描述其他语言还使用其他术语。这里我们继续使用 “按位” 和 “布尔” 等说法。9.7.1 按位运算符按位运算符作用于整数值的每个位上其结果为整数值。按位运算符类似于算术运算符但并不执行加法或减法运算而是对整数的位执行 AND、OR以及其他逻辑运算。这些运算符按照第 2 章介绍的真值表工作并行地对整数的所有位进行运算。表 9-3 编程语言中常用的按位运算符按位运算按位运算符ANDOR|XOR^NOT~许多编程语言包括 C 和 Python都使用表 9-3 所示的运算符进行按位运算。让我们看看 Python 中的按位运算x5y3axy bx|y上面代码的结果是 a 为 1b 为 7。我们来看二进制中的这些运算见图 9-4弄清楚为什么是这样的。图 9-4 对 5 和 3 进行 AND 和 OR 按位运算首先来看图 9-4 中的 AND 按位运算回忆一下第 2 章的内容AND 意味着当两个输入都是 1 时结果为 1。这里一次查看一列的位。如你所见对于两个输入来说只有最右边的位都为 1所以 AND 的结果是二进制的 0001 或十进制的 1。因此前面的代码为 a 赋值 1。对于 OR 运算只要有一个输入或两个输入都为 1结果就为 1。在本例中两个输入右边的 3 列位中每一列都至少有一位为 1所以结果是二进制的 0111 或十进制的 7。因此前面的代码为 b 赋值 7。9.7.2 布尔运算符高级编程语言中的另一种逻辑运算符是布尔运算符。布尔运算符处理布尔值其结果也是布尔值。我们先花点时间谈谈布尔值。布尔值指 “真” 和 “假”。不同的编程语言用不同的方式表示 “真” 和 “假”。布尔变量是一个确定的内存地址其中保存了一个布尔值“真” 或 “假”。例如在 Python 中我们可以用布尔变量来跟踪某商品是否在销售item_on_saleTrue。表达式可以计算为 “真” 或 “假”且其结果不用存储到变量中。例如根据 item_cost 变量的值表达式 item_cost 5 在运行时可以计算为 “真” 或 “假”。布尔运算符允许对布尔值执行逻辑运算比如 AND、OR 和 NOT。例如可以用 Python 的 AND 布尔运算符来检查两个条件是否都为真item_on_sale AND item_cost 5。AND 左右两边的表达式的计算结果都是布尔值所以整个表达式的计算结果也是布尔值。这里C 和 Python 使用不同的运算符如表 9-4 所示。表 9-4 C 和 Python 编程语言中的布尔运算符运算C 语言Python与and或||or非!not短路求值、||都有and、or都有优先级高→低!||notandor操作数判定0 为假非 0 为真False、None、0、空序列/空映射为假其余为真当我们讨论返回布尔值的运算符时不能遗漏比较运算符。比较运算符用来比较两个值并把比较结果评估为 “真” 或 “假”。例如 运算符比较两个数并确定一个是否大于另一个。表 9-5 展示了在 C 和 Python 中都使用的比较运算符。比较含义C 语言Python说明等于C 中不能写成是赋值不等于!!Python 旧写法已不推荐大于—小于—大于等于—小于等于—身份/地址比较无专门语法is、is notPython 中is比较是否是同一对象类似比较地址成员比较无in、not inPython 专用C 没有对应运算符在前面的例子 item_cost 5 中你已经看到了其中一个运算符的用法。注意对于等于运算符C 和 Python 都使用双等号因为单等号表示赋值。这就意味着 x5 是一个比较运算需返回 “真” 或 “假”而 x5 是一个赋值操作表示把 x 的值设置为 5。9.8 程序流布尔运算符和比较运算符用于计算表达式是否为真但这本身并不是很有用因为我们需要的是一种回应方式程序流或控制流语句可以改变程序的行为以响应某些条件。让我们来看一些跨编程语言的常见程序流结构。9.8.1 if 语句if 语句通常与 else 语句一起使用允许程序员在条件为真时执行一些操作。反过来else 语句允许程序在条件为假时执行另一些不同的操作。下面是一个 Python 示例本例中if 语句 ❶ 检查 age 变量引用的值是否小于 18。如果是它会输出一条消息指示用户非常年轻 ❷。如果 age 为 18 或更大的值 ❸那么 else 语句告诉系统输出另一条消息 ❹。下面是同一 “检查年纪” 的逻辑这次用 C 语言编写在 C 语言例子中请注意 if 语句后面使用的花括号 ❶❷。这些括号标记了响应 if 应执行的代码块。在 C 语言中代码块可以由多行代码构成不过当代码块由单行组成时可以忽略花括号。Python 不使用花括号来分隔代码块它使用缩进格式表示。在 Python 中具有相同缩进级别例如缩进 4 个空格的连续行被视为同一个代码块的组成部分。Python 还包含 elif 语句其含义为 “else if”。仅当某 elif 语句前面的 if 或 elif 语句为假时才处理该 elif 语句。同样的功能在 C 语言中可用 else 加上 if 来实现注意由于这里的代码块都是单行的所以省略了花括号。9.8.2 循环有些时候程序需要反复执行某个操作。while 循环允许代码重复运行直到满足某个条件。在下面的 Python 例子中while 循环被用于输出从 1 到 20 的数字初始时变量 n 被设置为 1。当 n 小于或等于 20 时才开始运行 while 循环。由于 n 初始为 1符合要求因此 while 循环运行输出 n 的值然后将 n 加 1。现在n 等于 2代码回到 while 循环的顶部。这个过程一直持续到 n 等于 21此时它不再满足 while 循环的要求所以循环结束。下面是用 C 语言实现的相同功能在这两个例子中while 循环的循环体使 n 的值递增。实际上还有一种更简洁的方式可以实现这一功能。for 循环允许对某个范围内的数字或一组值进行迭代以便程序员对其中每个数字执行一些操作。这里给出一个 C 语言的例子输出数字 1 到 10。for 循环声明 x 并将其初始值设置为 1 ❶表明当 x 小于或等于 10 时循环将继续 ❷最后声明 x 在循环体运行后递增 ❸。通过把这些信息全部放入单行的 for 语句中我们可以轻松地查看循环运行的条件。for 循环的循环体只输出 x 的值 ❹。Python 的 for 循环则采用不同的方法它允许程序对一组值中的每一个重复执行操作。下面的 Python 示例输出列表中的动物名首先声明一个动物名称列表变量并命名为 animal_list。在 Python 中列表是一个有序的值集合。接着在 for 循环中对 animal_list 中的每一项代码块都要运行一次且每次代码运行时列表中的当前值都被赋给 animal 变量。因此第一次运行循环体时animal 等于 cat程序输出 cat。接下来依次输出 dog 和 mouse。9.9 函数循环允许一组指令连续运行多次。但是还有一种情况也很常见即程序多次运行一组特定指令且不一定是循环。这样的指令可能需要从程序的不同部分、在不同的时间、用不同的输入和输出来调用。当程序员意识到同一代码需要出现在多个地方时他们可能会把这些代码编写成函数。函数是一组程序指令它可以被其他代码调用。函数可选地接收输入称为 “参数”并返回输出称为 “返回值”。不同的高级语言使用不同术语称呼函数例如子例程、过程或方法。在某些情况下这些不同的名称实际上传递了略有差异的含义但在这里我们坚持用术语 “函数”。把字符串转换成小写、将文本输出到屏幕、从互联网下载文件都是可以以函数的形式使用可重用代码执行的例子。程序员希望避免多次输入相同的代码因为多次输入相同的代码意味着维护了相同代码的多个副本且增加了程序总的代码量。这违反了 “不重复自己” (Don’t Repeat Yourself DRY) 的软件工程原则该原则鼓励减少重复性代码。函数是封装的另一个例子。我们在之前的硬件部分看到过封装这里我们再次看到它这次是软件封装。函数封装了代码块的内部细节并提供了使用该代码的接口。想要使用函数的开发人员只需了解其输入和输出无须完全了解该函数的内部工作方式。9.9.1 定义函数函数在使用前必须先定义。一旦定义了函数你就可以通过调用来使用它。“函数定义” 包括了函数名、输入参数、函数的程序语句称为函数体在某些语言中还有返回值类型。这里有一个 C 语言函数的例子即给定半径计算圆的面积的函数开始的 double 类型 ❶ 表示函数返回一个浮点数double 是 C 语言中的一种浮点类型。函数名为 areaOfCircle ❷旨在传递函数的功能——在本例中为计算圆的面积。函数接收一个名为 radius 的输入参数❸其类型也是 double。位于开始和结束花括号之间的是函数体它准确定义了函数的功能。我们声明了一个名为 area 的局部变量它的类型也是 double。函数用 π×radius2计算面积并把结果赋给 area 变量。最后函数返回 area 变量的值 ❹。注意area 变量的作用域是有限的它不能在函数外被访问。当函数返回时局部变量 area 被丢弃它可能存储在栈中但它的值可能通过处理器寄存器被返回给调用者。下面是一个类似的面积函数只不过这次是用 Python 编写的。让我们比较一下这两个函数。两个函数都用 π×radius2计算面积然后返回结果值。两个函数也都接收了一个名为 radius 的输入参数。C 语言版本显式定义返回类型为 doubleradius 的类型也是 double而 Python 语言版本没有要求声明类型。Python 中函数定义以 def 关键字开始。9.9.2 调用函数虽然在程序中定义了函数但函数不一定会被运行。函数定义只是让代码在需要时可以供其他代码调用。这种调用被称为 “函数调用”。调用代码传递所有需要的参数并把控制权转给函数。然后函数执行其代码并把控制权以及所有输出返还给调用者。下面演示一下如何在 C 语言中调用示例函数这是在 Python 中的调用当函数返回时由调用代码把返回值存储在某个地方。两个例子都声明用变量 area1 和 area2 保存函数调用的返回值。在两种语言中area1 是 12.56area2 是 4678.4744。实际上调用代码可以忽略返回值不将它们赋给变量但考虑到本函数的目的这不是十分有用。图 9-5 演示了调用函数时是如何把控制权暂时移交给被调用函数的。图 9-5 调用一个函数在图 9-5 中左边的 Python 代码调用 area_of_circle 函数向它传递输入参数 radius 的 值2.0。然后左边的代码进入等待状态直到右边的函数完成其工作。一旦右边的函数返回左边的代码就把返回值存储到变量 area1 中然后继续执行。9.9.3 使用库尽管程序员确实可以自定义函数但编程的一个重要部分是如何充分利用其他人已经编写好的函数。编程语言通常包括大量函数它们称为该语言的 “标准库”。这里“库” 是指给其他软件使用的代码集合。C 和 Python 都有标准库以提供函数完成诸如输出到控制台、处理文件和处理文本等功能。Python 的标准库使用特别广且备受推崇。虽然并非总是如此但一种语言的绝大多数实现都涵盖了该语言的标准库所以程序员可以依赖这些函数。除了标准库其他函数库也可以供编程语言使用。开发人员编写库给其他人使用并以源代码或编译文件的形式进行共享。这些库有时候是非正式共享的某些编程语言用众所周知且被接受的机制来发布库。一组共享的库称为包共享这种包的系统称为包管理器。C 语言有几种可用的包管理器但没有一个是被 C 程序员广泛接受成为标准的。Python 包含的包管理器称为 pip。pip 使得为 Python 安装社区开发软件库变得容易它常常被 Python 开发人员使用。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。