使用 Python 创造你自己的计算机游戏(游戏编程快速上手)第四版:致谢到第四章

简介: 使用 Python 创造你自己的计算机游戏(游戏编程快速上手)第四版:致谢到第四章

致谢


没有 No Starch Press 团队的出色工作,这本书就不可能问世。感谢我的出版商 Bill Pollock;感谢我的编辑 Laurel Chun、Jan Cash 和 Tyler Ortman,在整个过程中给予我的难以置信的帮助;感谢我的技术编辑 Ari Lacenski 进行了彻底的审查;感谢 Josh Ellingson 再次为我设计了出色的封面。

当我还是个孩子的时候,我第一次玩视频游戏就迷上了。但我不只是想玩视频游戏,我想制作它们。我找到了一本像这样的书,教我如何编写我的第一个程序和游戏。这很有趣,也很容易。我制作的第一个游戏就像这本书中的游戏一样。它们没有我父母为我买的任天堂游戏那么花哨,但它们是我自己制作的游戏。

现在,作为一个成年人,我依然喜欢编程,并且还能从中获得报酬。但即使你不想成为一名计算机程序员,编程也是一项有用且有趣的技能。它训练你的大脑以逻辑思维,制定计划,并在发现代码错误时重新考虑你的想法。

许多面向初学者的编程书籍分为两类。第一类包括那些不是教授编程而是“游戏创作软件”或者简化了太多以至于所教授的不再是编程的语言。另一类包括那些像数学教科书一样教授编程的书籍——所有原则和概念,读者很少能在现实生活中应用。这本书采取了不同的方法,通过制作视频游戏来教你编程。我会直接展示游戏的源代码,并从示例中解释编程原理。这种方法对我学习编程很有帮助。我学习其他人的程序是如何工作的,我就越能为自己的程序想到更多的点子。

你所需要的只是一台计算机,一个名为 Python 解释器的免费软件,以及这本书。一旦你学会了这本书中的游戏,你就能够自己开发游戏了。

计算机是令人难以置信的机器,学习如何编程它们并不像人们想象的那么难。计算机程序是一堆计算机能够理解的指令,就像故事书是读者能够理解的一堆句子一样。要指导计算机,你需要用计算机能够理解的语言编写程序。这本书将教你一种名为 Python 的编程语言。还有许多其他编程语言可以学习,比如 BASIC、Java、JavaScript、PHP 和 C++。

当我还是个孩子的时候,我学习了 BASIC,但像 Python 这样的新编程语言甚至更容易学习。Python 也被专业程序员在工作中和在编程时使用。而且它完全免费安装和使用——你只需要一个互联网连接来下载它。

因为视频游戏无非就是计算机程序,它们也是由指令组成的。从这本书中你将创建的游戏与 Xbox、PlayStation 或任天堂的游戏相比显得简单。这些游戏没有花哨的图形,因为它们的目的是教你编码基础。它们故意简单,这样你就可以专注于学习编程。游戏不一定要复杂才能有趣!

这本书是为谁准备的?

编程并不难,但很难找到教你用编程做有趣事物的材料。其他计算机书籍涵盖了许多新手程序员不需要的主题。这本书将教你如何编写自己的游戏;你将学到一项有用的技能,并有有趣的游戏可以展示!这本书适合:

  • 想自学编程的完全初学者,即使他们没有任何经验。
  • 想通过制作游戏学习编程的孩子和青少年。
  • 想要教授他人编程的成年人和教师。
  • 任何想通过学习专业编程语言来学习编程的人,无论年龄大小。

关于本书

在本书的大多数章节中,都介绍和解释了一个新的游戏项目。一些章节涵盖了额外的有用主题,比如调试。随着游戏的使用,新的编程概念也得到了解释,并且这些章节应该按顺序阅读。以下是每个章节的简要概述:

  • 第 1 章:交互式 Shell解释了如何使用 Python 的交互式 Shell 逐行实验代码。
  • 第 2 章:编写程序介绍了如何在 Python 的文件编辑器中编写完整的程序。
  • 第 3 章:猜数字中,您将编写本书中的第一个游戏,猜数字游戏,要求玩家猜一个秘密数字,然后提供关于猜测是否太高或太低的提示。
  • 第 4 章:讲笑话程序中,您将编写一个简单的程序,告诉用户几个笑话。
  • 第 5 章:龙之境界中,您将编写一个猜谜游戏,玩家必须在两个洞穴中进行选择:一个有友好的龙,另一个有饥饿的龙。
  • 第 6 章:使用调试器介绍了如何使用调试器来修复代码中的问题。
  • 第 7 章:使用流程图设计 Hangman解释了如何使用流程图来规划较长的程序,比如 Hangman 游戏。
  • 第 8 章:编写 Hangman 代码中,您将编写 Hangman 游戏,按照第 7 章的流程图。
  • 第 9 章:扩展 Hangman通过使用 Python 的字典数据类型,为 Hangman 游戏增加了新功能。
  • 第 10 章:井字游戏中,您将学习如何编写一个人机对战的井字游戏,使用人工智能。
  • 第 11 章:Bagels 推理游戏中,您将学习如何制作一个名为 Bagels 的推理游戏,玩家必须根据线索猜测秘密数字。
  • 第 12 章:笛卡尔坐标系解释了笛卡尔坐标系,您将在以后的游戏中使用它。
  • 第 13 章:声纳寻宝中,您将学习如何编写一个寻宝游戏,玩家在海洋中寻找失落的宝箱。
  • 第 14 章:凯撒密码中,您将创建一个简单的加密程序,让您编写和解码秘密消息。
  • 第 15 章:反转棋游戏中,您将编写一个高级的人机对战反转棋类游戏,其中有一个几乎无法战胜的人工智能对手。
  • 第 16 章:反转棋人工智能模拟扩展了第 15 章中的反转棋游戏,使多个人工智能在计算机对战中竞争。
  • 第 17 章:创建图形介绍了 Python 的pygame模块,并向您展示如何使用它来绘制 2D 图形。
  • 第 18 章:动画图形向您展示如何使用pygame来制作动画图形。
  • 第 19 章:碰撞检测中,您将学习如何在 2D 游戏中检测物体之间的碰撞。
  • 第 20 章:使用声音和图像中,您将通过添加声音和图像来改进您简单的pygame游戏。
  • 第 21 章:带声音和图像的躲避者游戏结合了第 17 章到第 20 章中的概念,制作了一个名为 Dodger 的动画游戏。

如何使用本书

本书的大多数章节都将以章节特色程序的示例运行开始。这个示例运行向你展示了当你运行程序时程序是什么样子的。用户输入的部分以粗体显示。

我建议你自己将每个程序的代码输入到 IDLE 的文件编辑器中,而不是下载或复制粘贴。如果你花时间输入代码,你会记得更多。

行号和缩进

在输入本书的源代码时,不要在每行开头输入行号。例如,如果你看到以下代码行,你不需要在左边输入9.,或者紧随其后的一个空格:

number = random.randint(1, 20)

你只需要输入这个:

number = random.randint(1, 20)

这些数字只是为了让本书能够指明程序中的特定行。它们不是实际程序源代码的一部分。

除了行号,按照本书中的代码精确输入。注意到一些代码行是以四个或八个(或更多)空格缩进的。行首的空格会改变 Python 解释指令的方式,所以它们非常重要。

让我们看一个例子。这里缩进的空格用黑色圆圈(•)标记,这样你就可以看到它们。

while guesses < 10:
••••if number == 42:
••••••••print('Hello')

第一行没有缩进,第二行缩进了四个空格,第三行缩进了八个空格。尽管本书中的示例没有黑色圆圈来标记空格,但在 IDLE 中每个字符的宽度都是相同的,所以你可以通过上一行或下一行的字符数量来计算空格的数量。

长代码行

有些代码指令在书中太长,无法放在一行上,会换到下一行。但是这一行在你的电脑屏幕上是可以放下的,所以不要按回车键,全部在一行上输入。你可以通过左边的行号来看一个新指令何时开始。这个例子只有两条指令:

print('This is the first instruction!xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxx')
print('This is the second instruction, not the third instruction.')

第一条指令在页面上换行到第二行,但第二行没有行号,所以你可以看到它仍然是代码的第一行。

下载和安装 Python

你需要安装一个叫做 Python 解释器的软件。解释器程序能理解你用 Python 写的指令。从现在开始,我会简称 Python 解释器软件为Python

在这一部分,我将向你展示如何下载和安装 Python 3——具体来说,是 Python 3.4——在 Windows、OS X 或 Ubuntu 上。Python 有比 3.4 更新的版本,但是pygame模块,它在第 17 章到第 21 章中使用,目前只支持到 3.4。

重要的是要知道 Python 2 和 Python 3 之间有一些重大的区别。本书中的程序使用的是 Python 3,如果你尝试用 Python 2 运行它们,你会得到错误。这是如此重要,事实上,我已经添加了一个卡通企鹅来提醒你。

在 Windows 上,从www.python.org/downloads/release/python-344/下载 Windows x86-64 MSI 安装程序,然后双击它。你可能需要输入计算机的管理员密码。按照安装程序在屏幕上显示的指令安装 Python,如下所列:

  1. 选择为所有用户安装,然后点击下一步
  2. 点击下一步跳过自定义 Python 部分,安装到C:\Python34文件夹。
  3. 点击下一步跳过自定义 Python 部分。

在 OS X 上,从www.python.org/downloads/release/python-344/下载 Mac OS X 64 位/32 位安装程序,然后双击它。按照安装程序在屏幕上显示的指令安装 Python,如下所列:

  1. 如果您收到警告“‘Python.mpkg’无法打开,因为它来自未知开发者”,请在右键单击Python.mpkg文件时按住 CONTROL,然后从出现的菜单中选择打开。您可能需要输入计算机的管理员密码。
  2. 点击继续通过欢迎部分,并点击同意接受许可协议。
  3. 选择Macintosh HD(或您的硬盘命名的任何内容)并点击安装

如果您正在运行 Ubuntu,您可以按照以下步骤从 Ubuntu 软件中心安装 Python:

  1. 打开 Ubuntu 软件中心。
  2. 在窗口右上角的搜索框中输入Python
  3. 选择IDLE(Python 3.4 GUI 64 位)
  4. 点击安装。您可能需要输入管理员密码以完成安装。

如果上述步骤不起作用,您可以在www.nostarch.com/inventwithpython/找到替代的 Python 3.4 安装说明。

启动 IDLE

IDLE 代表Interactive DeveLopment Environment。IDLE 就像一个用于编写 Python 程序的文字处理器。在每个操作系统上启动 IDLE 都是不同的:

  • 在 Windows 上,点击屏幕左下角的开始菜单,输入IDLE,然后选择IDLE(Python GUI)
  • 在 OS X 上,打开 Finder 并点击应用程序。双击**Python 3.**x,然后双击 IDLE 图标。
  • 在 Ubuntu 或其他 Linux 发行版上,打开终端窗口并输入idle3。您也可以点击屏幕顶部的应用程序,然后点击编程IDLE 3

当您第一次运行 IDLE 时出现的窗口是交互式 shell,如图 1 所示。您可以在>>>提示符下输入 Python 指令,Python 将执行它们。计算机执行指令后,新的>>>提示符将等待您的下一条指令。

图 1:IDLE 程序的交互式 shell

在线寻求帮助

您可以在www.nostarch.com/inventwithpython/找到本书的源代码文件和其他资源。如果您想要询问与本书相关的编程问题,请访问reddit.com/r/inventwithpython/,或者您可以将您的编程问题发送到[email protected]

在提问之前,请确保执行以下操作:

  • 如果您在本书中输入程序但出现错误,请在询问问题之前使用www.nostarch.com/inventwithpython#diff在线差异工具检查拼写错误。将您的代码复制并粘贴到差异工具中,以查找书中代码和您的代码之间的任何差异。
  • 搜索网络,看看是否有人已经提出(并回答)了您的问题。

请记住,您提出编程问题的措辞越好,其他人就越能帮助您。在提出编程问题时,请执行以下操作:

  • 解释您在出现错误时尝试做什么。这将让您的帮助者知道您是否完全走错了路。
  • 复制并粘贴整个错误消息和您的代码。
  • 提供您的操作系统和版本。
  • 解释您已经尝试解决问题的方法。这告诉人们您已经努力尝试自己解决问题。
  • 要有礼貌。不要要求帮助或者催促您的帮助者快速回复。

现在您知道如何寻求帮助,您将很快学会编写自己的电脑游戏!

一、交互式 shell

原文:inventwithpython.com/invent4thed/chapter1.html

译者:飞龙

协议:CC BY-NC-SA 4.0

在您可以制作游戏之前,您需要学习一些基本的编程概念。您将从本章开始学习如何使用 Python 的交互式 shell 并执行基本的算术运算。

本章涵盖的主题

  • 运算符
  • 整数和浮点数

  • 表达式
  • 语法错误
  • 将值存储在变量中

一些简单的数学

按照“启动 IDLE”中的步骤在第 xxvi 页上启动 IDLE。首先,您将使用 Python 解决一些简单的数学问题。交互式 shell 可以像计算器一样工作。在交互式 shell 的>>>提示符处键入2 + 2,然后按 ENTER 键。 (在某些键盘上,此键是 RETURN。)图 1-1 显示了这个数学问题在交互式 shell 中的样子-请注意它响应数字4

图 1-1: 在交互式 shell 中输入 2 + 2

这个数学问题是一个简单的编程指令。加号(+)告诉计算机将数字22相加。计算机执行此操作,并在下一行返回数字4。表 1-1 列出了 Python 中可用的其他数学符号。

表 1-1: 数学运算符

运算符 操作
+ 加法
- 减法
* 乘法
/ 除法

减号(-)减去数字,星号(*)乘以数字,斜杠(/)除以数字。这样使用时,+-*/被称为运算符。运算符告诉 Python 如何处理它们周围的数字。

整数和浮点数

整数(或简称整数)是诸如4990的整数。浮点数(或简称浮点数)是分数或带有小数点的数字,如3.542.15.0。在 Python 中,5是一个整数,但5.0是一个浮点数。这些数字被称为。(稍后我们将学习除了数字之外的其他种类的值。)在您在 shell 中输入的数学问题中,22是整数值。

表达式

数学问题2 + 2表达式的一个例子。如图 1-2 所示,表达式由值(数字)和运算符(数学符号)组成,产生代码可以使用的新值。计算机可以在几秒钟内解决数百万个表达式。

图 1-2:表达式由值和运算符组成。

尝试将其中一些表达式输入交互式 shell,每次输入后按 ENTER:

>>> 2+2+2+2+2
10
>>> 8*6
48
>>> 10-5+6
11
>>> 2  +        2
4

这些表达式看起来都像普通的数学方程,但请注意2 + 2示例中的所有空格。在 Python 中,您可以在值和运算符之间添加任意数量的空格。但是,当将它们输入交互式 shell 时,您必须始终从行的开头(没有空格)开始指令。

评估表达式

当计算机解决表达式10 + 5并返回值15时,它已经评估了表达式。评估表达式将表达式减少为单个值,就像解决数学问题将问题减少为单个数字:答案。例如,表达式10 + 510 + 3 + 2都求值为15

当 Python 评估表达式时,它遵循与您进行数学运算时一样的操作顺序。只有几条规则:

  • 括号内表达式的部分首先进行评估。
  • 乘法和除法在加法和减法之前进行。
  • 评估是从左到右执行的。

表达式 1 + 2 * 3 + 4 求值为 11,而不是 13,因为首先评估 2 * 3。如果表达式是 (1 + 2) * (3 + 4),它将求值为 21,因为括号内的 (1 + 2)(3 + 4) 在乘法之前被评估。

表达式可以是任意大小,但它们总是会求值为一个单一的值。即使单个值也是表达式。例如,表达式 15 求值为值 15。表达式 8 * 3 / 2 + 2 + 7 - 9 通过以下步骤求值为值 12.0

尽管计算机正在执行所有这些步骤,但你在交互式 shell 中看不到它们。交互式 shell 只会显示结果:

>>> 8 * 3 / 2 + 2 + 7 - 9
12.0

注意,带有 / 除法运算符的表达式总是求值为浮点数;例如,24 / 2 求值为 12.0。即使有一个浮点数值的数学运算也会求值为浮点数值,所以 12.0 + 2 求值为 14.0

语法错误

如果你在交互式 shell 中输入 5 +,你会得到以下错误消息:

>>> 5 +
SyntaxError: invalid syntax

这个错误发生是因为 5 + 不是一个表达式。表达式是由运算符连接的值,+ 运算符期望在它之前之后有一个值。当期望的值缺失时,会出现错误消息。

SyntaxError 意味着 Python 无法理解指令,因为你输入错误了。计算机编程不仅仅是给计算机指令,还要知道如何正确地给它这些指令。

不过不要担心犯错。错误不会损坏你的计算机。只需在下一个 >>> 提示符下正确地重新输入指令到交互式 shell 中。

在变量中存储值

当一个表达式求值为一个值时,你可以通过将其存储在变量中来稍后使用该值。把变量想象成一个可以容纳值的盒子。

赋值语句会将一个值存储在变量中。输入变量名称,然后是等号(=),这被称为赋值运算符,然后是要存储在变量中的值。例如,输入以下内容到交互式 shell 中:

>>> spam = 15
>>>

spam 变量的盒子现在存储值 15,如图 1-3 所示。

图 1-3:变量就像可以容纳值的盒子。

当你按下 ENTER 键时,你不会看到任何响应。在 Python 中,如果没有出现错误消息,你就知道指令是成功的。>>> 提示符会出现,这样你就可以输入下一个指令。

与表达式不同,语句是不会求值为任何值的指令。这就是为什么在 spam = 15 后的交互式 shell 中的下一行没有显示任何值。如果你对哪些指令是表达式,哪些是语句感到困惑,记住表达式会求值为一个单一的值。任何其他类型的指令都是语句。

变量存储值,而不是表达式。例如,考虑语句 spam = 10 + 5spam = 10 + 7 - 2 中的表达式。它们都求值为 15。最终结果是一样的:两个赋值语句都将值 15 存储在变量 spam 中。

一个好的变量名称描述了它包含的数据。想象一下,你搬到了一个新房子,并且给所有的搬运箱贴上了 东西 的标签。你永远找不到任何东西!spameggsbacon 这些变量名称是本书中用于变量的示例名称。

第一次在赋值语句中使用变量时,Python 会创建该变量。要检查变量中的值,输入变量名称到交互式 shell 中:

>>> spam = 15
>>> spam
15

表达式 spam 的值是变量 spam 中的值:15

你也可以在表达式中使用变量。尝试在交互式 shell 中输入以下内容:

>>> spam = 15
>>> spam + 5
20

你将变量spam的值设置为15,所以输入spam + 5就像输入表达式15 + 5。以下是spam + 5被评估的步骤:

在赋值语句创建变量之前,你不能使用变量。如果你尝试这样做,Python 会给你一个NameError,因为还没有这样的变量。变量名拼写错误也会导致这个错误:

>>> spam = 15
>>> spma
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    spma
NameError: name 'spma' is not defined

出现错误是因为有一个spam变量,但没有spma变量。

你可以通过输入另一个赋值语句来更改变量中存储的值。例如,将以下内容输入交互式 shell 中:

>>> spam = 15
>>> spam + 5
20
>>> spam = 3
>>> spam + 5
8

当你第一次输入spam + 5时,表达式的值为20,因为你在spam中存储了15。然而,当你输入spam = 3时,变量的盒子中的值15被替换或覆盖为值3,因为变量一次只能保存一个值。因为spam的值现在是3,所以当你输入spam + 5时,表达式的值为8。覆盖就像是从变量的盒子中取出一个值,然后放入一个新值,如图 1-4 所示。

图 1-4:spam中的值153*覆盖。

你甚至可以使用spam变量中的值来为spam赋一个新值:

>>> spam = 15
>>> spam = spam + 5
20

赋值语句spam = spam + 5表示,“spam变量的新值将是spam的当前值加上五。”要多次增加spam中的值5,请将以下内容输入交互式 shell 中:

>>> spam = 15
>>> spam = spam + 5
>>> spam = spam + 5
>>> spam = spam + 5
>>> spam
30

在这个例子中,你在第一条语句中为spam赋了一个值15。在下一条语句中,你将5加到spam的值上,并将spam赋予新值spam + 5,这个值为20。当你这样做三次时,spam的值为30

到目前为止,我们只看了一个变量,但是你可以在你的程序中创建尽可能多的变量。例如,让我们给两个名为eggsbacon的变量分配不同的值,如下所示:

>>> bacon = 10
>>> eggs = 15

现在bacon变量中有10eggs变量中有15。每个变量都是它自己的盒子,有自己的值,如图 1-5 所示。

图 1-5:baconeggs变量分别存储值。

在交互式 shell 中输入spam = bacon + eggs,然后检查spam的新值:

>>> bacon = 10
>>> eggs = 15
>>> spam = bacon + eggs
>>> spam
25

spam中的值现在是25。当你加上baconeggs时,你正在加上它们的值,分别为1015。变量包含值,而不是表达式,所以spam变量被赋予了值25,而不是表达式bacon + eggs。在spam = bacon + eggs语句将值25赋给spam之后,改变baconeggs不会影响spam

总结

在本章中,你学习了编写 Python 指令的基础知识。因为计算机没有常识,只能理解特定的指令,Python 需要你准确告诉它要做什么。

表达式是值(如25)与运算符(如+-)的组合。Python 可以评估表达式,即将表达式简化为单个值。你可以将值存储在变量中,以便你的程序可以记住这些值并在以后使用它们。

Python 中还有其他类型的运算符和值。在下一章中,你将学习一些更基本的概念,并编写你的第一个程序。你将学习如何在表达式中处理文本。Python 不仅仅局限于数字;它不仅仅是一个计算器!

二、编写程序

原文:inventwithpython.com/invent4thed/chapter2.html

译者:飞龙

协议:CC BY-NC-SA 4.0

现在让我们看看 Python 可以用文本做什么。几乎所有程序都向用户显示文本,并且用户通过键盘向程序输入文本。在本章中,您将制作您的第一个程序,该程序可以做这两件事。您将学习如何将文本存储在变量中,组合文本,并在屏幕上显示文本。您将创建的程序显示问候语Hello world!并要求用户输入姓名。

本章涵盖的主题

  • 字符串
  • 字符串连接
  • 数据类型(如字符串或整数)
  • 使用文件编辑器编写程序
  • 在 IDLE 中保存和运行程序
  • 执行流程
  • 注释
  • print() 函数
  • input() 函数
  • 大小写敏感

字符串值

在 Python 中,文本值称为字符串。字符串值可以像整数或浮点值一样使用。您可以将字符串存储在变量中。在代码中,字符串值以单引号'开始和结束。将此代码输入交互式 shell:

>>> spam = 'hello'

单引号告诉 Python 字符串从哪里开始和结束。它们不是字符串值文本的一部分。现在,如果您在交互式 shell 中输入spam,您将看到spam变量的内容。请记住,Python 将变量求值为变量内部存储的值。在这种情况下,这是字符串'hello'

>>> spam = 'hello'
>>> spam
'hello'

字符串可以包含任何键盘字符,并且可以任意长。以下都是字符串的示例:

'hello'
'Hi there!'
'KITTENS'
'7 apples, 14 oranges, 3 lemons'
'Anything not pertaining to elephants is irrelephant.'
'A long time ago, in a galaxy far, far away...'
'O*&#wY%*&OCfsdYO*&gfC%YO*&%3yc8r2'

字符串连接

您可以使用运算符将字符串值与运算符组合成表达式,就像整数和浮点值一样。当您使用+运算符组合两个字符串时,称为字符串连接。将'Hello' + 'World!'输入交互式 shell:

>>> 'Hello' + 'World!'
'HelloWorld!'

该表达式求值为单个字符串值'HelloWorld!'。两个连接的字符串中没有空格,因此单词之间也没有空格,与以下示例不同:

>>> 'Hello ' + 'World!'
'Hello World!'

+ 运算符在字符串和整数值上的工作方式不同,因为它们是不同的数据类型。所有值都有一个数据类型。值'Hello'的数据类型是字符串。值5的数据类型是整数。数据类型告诉 Python 在评估表达式时应该做什么。+ 运算符连接字符串值,但是添加整数和浮点数值。

在 IDLE 的文件编辑器中编写程序

到目前为止,您一直在逐个输入 IDLE 的交互式 shell 中的指令。但是,当您编写程序时,您会输入多个指令并一次性运行它们,这就是您接下来要做的事情。现在是时候编写您的第一个程序了!

除了解释器,IDLE 还有另一个部分称为文件编辑器。要打开它,请单击交互式 shell 顶部的文件菜单。然后选择新建文件。将出现一个空白窗口,供您输入程序代码,如图 2-1 所示。

图 2-1:文件编辑器(左)和交互式 shell(右)

这两个窗口看起来很相似,但请记住:交互式 shell 将显示>>>提示,而文件编辑器不会。

创建 Hello World 程序

程序员传统上会让他们的第一个程序在屏幕上显示Hello world!。现在您将创建自己的 Hello World 程序。

当输入程序时,请记住不要输入每行代码开头的数字。它们是为了让本书可以按行号引用代码。文件编辑器的右下角将告诉您光标在哪里,这样您就可以检查自己在哪一行代码上。图 2-2 显示光标在第 1 行(在编辑器上下移动)和第 0 列(在左右移动)。

图 2-2:文件编辑器的右下角告诉您光标在哪一行

将以下文本输入到新的文件编辑器窗口中。这是程序的源代码。它包含了 Python 在运行程序时将遵循的指令。

hello.py

# This program says hello and asks for my name.
print('Hello world!')
print('What is your name?')
myName = input()
print('It is good to meet you, ' + myName)

IDLE 将使用不同的颜色写入不同类型的指令。在输入代码后,窗口应该看起来像图 2-3。

图 2-3:输入代码后文件编辑器的样子

检查确保您的 IDLE 窗口看起来一样。

保存您的程序

输入源代码后,请单击文件 !image](https://gitcode.net/OpenDocCN/flygon-trans-202401/-/raw/master/docs/inv-uron-cmp-gm-py-4e/img/6213f577c15feb006bdab7161d1cfc75.png) 另存为 进行保存。或者按下 CTRL-S 进行快捷键保存。[图 2-4 显示将打开的另存为窗口。在文件名文本字段中输入hello.py,然后单击保存

图 2-4:保存程序

在编写程序时,应该经常保存程序。这样,如果计算机崩溃或者您意外退出 IDLE,您不会丢失太多工作。

要加载之前保存的程序,请单击文件打开。在出现的窗口中选择hello.py文件,然后单击打开按钮。您保存的hello.py程序将在文件编辑器中打开。

运行您的程序

现在是运行程序的时候了。单击运行运行模块。或者从文件编辑器中按下 F5(在 OS X 上是 FN-5)。您的程序将在交互式 shell 中运行。

当程序要求输入您的名字时,请输入。这将看起来像图 2-5。

图 2-5:运行 hello.py 后的交互式 shell

当您输入您的名字并按下回车键时,程序将以您的名字向您问候。恭喜!您已经编写了您的第一个程序,现在是一名计算机程序员。再次按 F5 运行程序,然后输入另一个名字。

如果出现错误,请使用在线 diff 工具将您的代码与本书的代码进行比较,网址为https://www.nostarch.com/inventwithpython#diff](https://www.nostarch.com/inventwithpython#diff)。从文件编辑器中复制并粘贴您的代码到网页上,然后单击比较按钮。该工具将突出显示您的代码与本书中代码之间的任何差异,如[图 2-6 所示。

在编码过程中,如果出现以下形式的NameError,这意味着您正在使用 Python 2 而不是 Python 3。

Hello world!
What is your name?
Albert
Traceback (most recent call last):
  File "C:/Python26/test1.py", line 4, in <module>
    myName = input()
  File "<string>", line 1, in <module>
NameError: name 'Albert' is not defined

要解决问题,请安装 Python 3.4 并重新运行程序。(参见“下载和安装 Python”第 xxv 页。)

图 2-6:使用 diff 工具www.nostarch.com/inventwithpython#diff

Hello World 程序的工作原理

每行代码都是 Python 解释的一条指令。这些指令组成了程序。计算机程序的指令就像食谱中的步骤一样。Python 按顺序完成程序中的每个指令,从程序的顶部向下移动。

Python 当前在程序中工作的步骤称为执行。程序开始时,执行位于第一条指令处。执行指令后,Python 会向下移动到下一条指令。

让我们看看代码的每一行都在做什么。我们将从第 1 行开始。

程序员的注释

Hello World 程序的第一行是注释

# This program says hello and asks for my name.

井号(#)后面的任何文本都是注释。注释是程序员关于代码功能的注释;它们不是为 Python 编写的,而是为你,程序员。Python 在运行程序时会忽略注释。程序员通常在代码顶部放置注释,以便为他们的程序命名。Hello World 程序中的注释告诉你程序会打招呼并询问你的名字。

函数:程序内的迷你程序

函数有点像程序中的迷你程序,其中包含 Python 执行的几条指令。函数的好处是你只需要知道它们做什么,而不需要知道它们是如何做的。Python 已经提供了一些内置函数。我们在 Hello World 程序中使用了print()input()

函数调用是一条指令,告诉 Python 运行函数内部的代码。例如,你的程序调用print()函数在屏幕上显示一个字符串。print()函数将你在括号中输入的字符串作为输入,并在屏幕上显示该文本。

print()函数

Hello World 程序的第 2 行和第 3 行是对print()的调用:

print('Hello world!')
print('What is your name?')

函数调用括号中的值是参数。第 2 行print()函数调用的参数是'Hello world!',第 3 行print()函数调用的参数是'What is your name?'。这称为传递参数给函数。

input()函数

第 4 行是一个带有变量myName和函数调用input()的赋值语句:

myName = input()

当调用input()时,程序会等待用户输入文本。用户输入的文本字符串将成为函数调用评估的值。函数调用可以在任何可以使用值的表达式中使用。

函数调用评估的值称为返回值。(实际上,“函数调用返回的值”和“函数调用评估的值”意思相同。)在这种情况下,input()函数的返回值是用户输入的字符串:他们的名字。如果用户输入Albertinput()函数调用将求值为字符串'Albert'。评估如下:

这就是字符串值'Albert'存储在myName变量中的方式。

函数调用中的表达式

Hello World 程序的最后一行是另一个print()函数调用:

print('It is good to meet you, ' + myName)

表达式'It is good to meet you, ' + myNameprint()的括号中。因为参数总是单个值,Python 首先评估这个表达式,然后将该值作为参数传递。如果myName中存储的是'Albert',评估如下:

这就是程序通过名字向用户问候的方式。

程序结束

一旦程序执行最后一行,它就会终止退出。这意味着程序停止运行。Python 忘记了所有存储在变量中的值,包括存储在myName中的字符串。如果再次运行程序并输入不同的名称,程序将认为那是你的名字。

Hello world!
What is your name?
Carolyn
It is good to meet you, Carolyn

记住,计算机会完全按照你编程的指令执行。计算机很笨,只会严格按照你给它的指令执行。计算机不在乎你输入你的名字、别人的名字或者一些愚蠢的东西。输入任何你想输入的东西。计算机会以同样的方式对待它:

Hello world!
What is your name?
poop
It is good to meet you, poop

变量命名

给变量起描述性的名称可以更容易理解程序的功能。您可以将myName变量命名为abrahamLincolnnAmE,Python 也会运行程序。但这些名称并不能告诉您有关变量可能包含的信息。正如第 1 章所讨论的,如果您搬家并且将每个搬运箱标记为Stuff,那将毫无帮助!本书的交互式 Shell 示例使用变量名spameggsbacon,因为这些示例中的变量名并不重要。然而,本书的程序都使用描述性名称,您的程序也应该如此。

变量名是区分大小写的,这意味着不同大小写的相同变量名被视为不同的变量。因此,在 Python 中,spamSPAMSpamsPAM是四个不同的变量。它们各自包含自己的值。在程序中使用不同大小写的变量是一个不好的主意。而是应该为您的变量使用描述性的名称。

变量名通常是小写的。如果变量名中有多个单词,最好将第一个单词之后的每个单词大写。例如,变量名whatIHadForBreakfastThisMorningwhatihadforbreakfastthismorning更容易阅读。以这种方式大写您的变量称为驼峰命名法(因为它类似于骆驼背上的驼峰),它可以使您的代码更易读。程序员也更喜欢使用更短的变量名来使代码更易于理解:breakfastfoodThisMorningwhatIHadForBreakfastThisMorning更易读。这些是约定——在 Python 编程中做事情的可选但标准方式。

总结

一旦您了解如何使用字符串和函数,您就可以开始制作与用户交互的程序。这很重要,因为文本是用户和计算机之间主要的交流方式。用户通过键盘使用input()函数输入文本,计算机则使用print()函数在屏幕上显示文本。

字符串只是一种新数据类型的值。所有值都有数据类型,值的数据类型会影响+运算符的功能。

函数用于执行程序中的复杂指令。Python 有许多内置函数,您将在本书中学习到。函数调用可以在表达式中的任何值处使用。

您的程序中 Python 当前正在执行的指令或步骤称为执行。在第 3 章中,您将学习如何使执行以除了直接向下执行程序之外的其他方式移动。一旦您学会了这一点,您就可以开始创建游戏了!

三、猜数字

原文:inventwithpython.com/invent4thed/chapter3.html

译者:飞龙

协议:CC BY-NC-SA 4.0

在本章中,你将制作一个猜数字游戏。计算机会想一个从 1 到 20 的秘密数字,并要求用户猜测。每次猜测后,计算机会告诉用户数字是太高还是太低。如果用户能在六次内猜中数字,他们就赢了。

这是一个很好的编程游戏,因为它涵盖了短程序中的许多编程概念。你将学习如何将值转换为不同的数据类型,以及何时需要这样做。由于这个程序是一个游戏,从现在开始我们将称用户为玩家

本章涵盖的主题

  • import 语句
  • 模块
  • randint() 函数
  • for 语句

  • str()int()float() 函数
  • 布尔值
  • 比较运算符
  • 条件
  • === 之间的区别
  • if 语句
  • break 语句

猜数字的示例运行

当运行猜数字程序时,玩家的输入如下所示。玩家的输入以粗体标记。

Hello! What is your name?
Albert
Well, Albert, I am thinking of a number between 1 and 20.
Take a guess.
10
Your guess is too high.
Take a guess.
2
Your guess is too low.
Take a guess.
4
Good job, Albert! You guessed my number in 3 guesses!

猜数字的源代码

通过单击文件新建窗口 打开一个新的文件编辑器窗口。在出现的空白窗口中,输入源代码并将其保存为 guess.py。然后按 F5 运行程序。

当你把这段代码输入到文件编辑器中时,一定要注意行首的空格。有些行需要缩进四个或八个空格。

如果输入此代码后出现错误,请使用在线差异工具将你输入的代码与本书代码进行比较,网址为 www.nostarch.com/inventwithpython#diff

guess.py

# This is a Guess the Number game.
import random
guessesTaken = 0
print('Hello! What is your name?')
myName = input()
number = random.randint(1, 20)
print('Well, ' + myName + ', I am thinking of a number between 1 and 20.')
for guessesTaken in range(6):
    print('Take a guess.') # Four spaces in front of "print"
    guess = input()
    guess = int(guess)
    if guess < number:
        print('Your guess is too low.') # Eight spaces in front of "print"
    if guess > number:
        print('Your guess is too high.')
    if guess == number:
        break
if guess == number:
    guessesTaken = str(guessesTaken + 1)
    print('Good job, ' + myName + '! You guessed my number in ' +
          guessesTaken + ' guesses!')
if guess != number:
    number = str(number)
    print('Nope. The number I was thinking of was ' + number + '.')

导入 random 模块

让我们来看看这个程序的前两行:

# This is a Guess the Number game.
import random

第一行是一个注释,你在第 2 章中见过。记住 Python 会忽略 # 字符后的所有内容。这里的注释只是提醒我们这个程序的作用是什么。

第二行是一个 import 语句。记住,语句是执行某些操作的指令,但不像表达式那样求值。你已经见过赋值语句,它将一个值存储在一个变量中。

虽然 Python 包含许多内置函数,但有些函数是写在称为模块的单独程序中的。你可以通过使用 import 语句将这些函数的模块导入到你的程序中来使用这些函数。

第 2 行导入了 random 模块,以便程序可以调用 randint() 函数。这个函数将为玩家生成一个随机数来猜测。

现在你已经导入了 random 模块,需要设置一些变量来存储程序稍后将使用的值。

第 4 行创建了一个名为 guessesTaken 的新变量:

guessesTaken = 0

你将把玩家猜测的次数存储在这个变量中。由于在程序的这一点上玩家还没有进行任何猜测,所以在这里存储整数 0

print('Hello! What is your name?')
myName = input()

第 6 行和第 7 行与第 2 章中的 Hello World 程序中的行相同。程序员经常重用其他程序中的代码来节省工作量。

第 6 行是对 print() 的函数调用。记住,函数就像你程序中的一个小型程序。当你的程序调用一个函数时,它会运行这个小程序。print() 中的代码会在屏幕上显示你传递给它的字符串参数。

第 7 行让玩家输入他们的名字并将其存储在 myName 变量中。记住,这个字符串可能并不是玩家的真实姓名;它只是玩家输入的任何字符串。计算机是愚蠢的,会按照它们的指令执行,不管怎样。

使用 random.randint()函数生成随机数

现在你的其他变量都设置好了,你可以使用random模块的函数来设置计算机的秘密数字:

number = random.randint(1, 20)

第 9 行调用了一个名为randint()的新函数,并将返回值存储在number中。记住,函数调用可以是表达式的一部分,因为它们会求值为一个值。

randint()函数由random模块提供,所以你必须使用random.randint()(别忘了句号!)告诉 Python 函数randint()random模块中。

randint()将返回两个整数参数之间(包括这两个整数)的随机整数。第 9 行在函数名后的括号内传递了用逗号分隔的120randint()返回的随机整数存储在一个名为number的变量中——这就是玩家试图猜测的秘密数字。

只需片刻,回到交互式 shell,输入import random导入random模块。然后输入random.randint(1, 20)看看函数调用的结果。它将返回一个介于120之间的整数。再次重复代码,函数调用将返回另一个整数。randint()函数每次返回一个随机整数,就像掷骰子每次都会得到一个随机数一样。例如,输入以下内容到交互式 shell。当你调用randint()函数时得到的结果可能会不同(毕竟是随机的!)。

>>> import random
>>> random.randint(1, 20)
12
>>> random.randint(1, 20)
18
>>> random.randint(1, 20)
3
>>> random.randint(1, 20)
18
>>> random.randint(1, 20)
7

你也可以通过改变参数尝试不同范围的数字。例如,输入random.randint(1, 4)来获得介于14之间的整数(包括14)。或者尝试random.randint(1000, 2000)来获得介于10002000之间的整数。

在交互式 shell 中输入此代码,看看你得到了什么数字:

>>> random.randint(1, 4)
3
>>> random.randint(1000, 2000)
1294

你可以稍微改变游戏的代码,使游戏的行为有所不同。在我们的原始代码中,我们使用介于120之间的整数:

number = random.randint(1, 20)
print('Well, ' + myName + ', I am thinking of a number between 1 and 20.')

尝试将整数范围改为(1, 100)

number = random.randint(1, 100)
print('Well, ' + myName + ', I am thinking of a number between 1 and 100.')

现在计算机将想一个介于1100之间的整数,而不是120。改变第 9 行将改变随机数的范围,但记得同时改变第 10 行,以便游戏告诉玩家新的范围而不是旧的范围。

你可以在游戏中随时使用randint()函数添加随机性。你会在许多游戏中使用随机性。(想想有多少桌游使用骰子。)

欢迎玩家

计算机给number分配一个随机整数后,会向玩家打招呼:

print('Well, ' + myName + ', I am thinking of a number between 1 and 20.')

在第 10 行,print()欢迎玩家,并告诉他们计算机正在想一个随机数。

乍一看,第 10 行可能看起来有多个字符串参数,但仔细检查一下。三个字符串之间的+运算符将它们连接成一个字符串。而这个字符串是传递给print()的参数。如果你仔细看,你会发现逗号在引号内并且是字符串的一部分。

流程控制语句

在之前的章节中,程序执行从程序顶部的指令开始,直接向下移动,按顺序执行每个指令。但是通过forifelsebreak语句,你可以根据条件使执行循环或跳过指令。这些类型的语句是流程控制语句,因为它们改变程序执行的流程,使其在程序中移动时改变。

使用循环重复代码

第 12 行是一个for语句,表示for循环的开始:

for guessesTaken in range(6):

循环让你可以一遍又一遍地执行代码。第 12 行将重复其代码六次。for语句以for关键字开始,后面跟着一个新的变量名、in关键字、调用range()函数指定它应该执行的循环次数,以及一个冒号。让我们再讨论一些其他概念,这样你就可以使用循环了。

使用块进行分组

几行代码可以组合在一起形成一个。代码块中的每一行都至少以与块中第一行相同数量的空格开头。通过查看行首的空格数量,可以确定块的开始和结束。这就是所谓的缩进

Python 程序员通常使用四个额外空格来开始一个块。任何后续的行,只要缩进相同,都是块的一部分。当有一行代码的缩进与块开始之前的缩进相同时,块就结束了。也可以在其他块内有块。图 3-1 显示了一个带有轮廓和编号的代码图。

图 3-1:块及其缩进的示例。灰色点代表空格。

在图 3-1 中,第 12 行没有缩进,也不在任何块内。第 13 行缩进了四个空格。由于这一行的缩进比上一行多,一个新的块从这里开始。之后的每一行,只要缩进相同或更多,都被视为块 ➊ 的一部分。如果 Python 遇到另一行的缩进少于块的第一行,那么块已经结束。空行会被忽略。

第 18 行缩进了八个空格,开始了块 ➋。这个块是块 ➊ 的。但是下一行,第 20 行,只缩进了四个空格。由于缩进减少,您知道第 18 行的块 ➋ 已经结束了,并且因为第 20 行的缩进与第 13 行相同,所以它在块 ➊ 中。

第 21 行再次增加缩进到八个空格,因此又开始了一个新的块:块 ➌。在第 23 行,我们退出了块 ➌,在第 24 行,我们进入了块 ➍。块 ➊ 和块 ➍ 都在第 24 行结束。

使用 for 语句进行循环

for语句标志着循环的开始。循环重复执行相同的代码。当执行到达for语句时,它进入for语句后面的块。在运行完块中的所有代码后,执行将返回到块的顶部,重新运行所有代码。

在交互式 shell 中输入以下内容:

>>> for i in range(3):
    print('Hello! i is set to', i)
Hello! i is set to 0
Hello! i is set to 1
Hello! i is set to 2

注意,在输入for i in range(3):并按 ENTER 后,交互式 shell 没有显示另一个>>>提示,因为它期望您输入一块代码。在输入最后一条指令后再次按 ENTER,告诉交互式 shell 您已经输入完代码块了。(这仅适用于在交互式 shell 中工作时。在文件编辑器中编写*.py*文件时,不需要插入空行。)

让我们看一下guess.py第 12 行的for循环:

for guessesTaken in range(6):
    print('Take a guess.') # Four spaces in front of "print"
    guess = input()
    guess = int(guess)
    if guess < number:
        print('Your guess is too low.') # Eight spaces in front of "print"
    if guess > number:
        print('Your guess is too high.')
    if guess == number:
        break
if guess == number:

在猜数字游戏中,for块从第 12 行的for语句开始,而for块之后的第一行是第 26 行。

for语句的条件后总是有一个冒号(:)。以冒号结尾的语句期望下一行有一个新的块。这在图 3-2 中有所体现。

图 3-2:循环执行流

图 3-2 显示了执行流程。执行将进入第 13 行的for块并继续向下进行。一旦程序到达for块的末尾,执行不会继续向下执行,而是会循环回到第 13 行for块的开始。这样做了六次,因为for语句中调用了range(6)函数。执行循环的每一次称为迭代

for语句视为“执行以下代码块一定次数”。

获取玩家的猜测

第 13 行和第 14 行要求玩家猜测秘密数字,并让他们输入他们的猜测:

print('Take a guess.') # Four spaces in front of "print"
    guess = input()

玩家输入的数字存储在名为guess的变量中。

使用 int()、float()和 str()函数转换值

第 15 行调用了一个名为int()的新函数:

guess = int(guess)

int()函数接受一个参数,并将参数的值作为整数返回。

在交互式 shell 中输入以下内容,以查看int()函数的工作原理:

>>> int('42')
42

int('42')调用将返回整数值42

>>> 3 + int('2')
5

3 + int('2')这一行显示了一个使用int()返回值作为表达式一部分的表达式。它求值为整数值5

尽管你可以将字符串传递给int(),但你不能传递任意字符串。将'forty-two'传递给int()将导致错误:

>>> int('forty-two')
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    int('forty-two')
ValueError: invalid literal for int() with base 10: 'forty-two'

传递给int()的字符串必须由数字组成。

在猜数字游戏中,我们使用input()函数获取玩家的数字。记住,input()函数总是返回玩家输入的文本的字符串。如果玩家输入5input()函数将返回字符串值'5',而不是整数值5。但是我们稍后需要将玩家的数字与整数进行比较,Python 不能使用<>比较运算符来比较字符串和整数值:

>>> 4 < '5'
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    4 < '5'
TypeError: unorderable types: int() < str()

因此,我们需要将字符串转换为整数:

guess = input()
    guess = int(guess)

在第 14 行,我们将guess变量赋值为玩家输入的数字的字符串值。第 15 行用int()返回的整数值覆盖了guess中的字符串值。代码int(guess)返回了一个基于提供的字符串的新整数值,guess =将该新值赋给了guess。这样,程序后面的代码可以比较guess是否大于、小于或等于number变量中的秘密数字。

float()str()函数同样会返回传递给它们的参数的浮点数和字符串版本。在交互式 shell 中输入以下内容:

>>> float('42')
42.0
>>> float(42)
42.0

当字符串'42'或整数42传递给float()时,将返回浮点数42.0

现在尝试使用str()函数:

>>> str(42)
'42'
>>> str(42.0)
'42.0'

当整数42传递给str()时,将返回字符串'42'。但是当浮点数42.0传递给str()时,将返回字符串'42.0'

使用int()float()str()函数,你可以将一个数据类型的值转换为另一个数据类型的值。

布尔数据类型

Python 中的每个值都属于一个数据类型。到目前为止介绍的数据类型有整数、浮点数、字符串,现在还有布尔值。布尔数据类型只有两个值:TrueFalse。布尔值必须用大写的TF输入,其余值的名称用小写。

布尔值可以像其他数据类型一样存储在变量中:

>>> spam = True
>>> eggs = False

在这个例子中,你将spam设置为True,将eggs设置为False。记得将第一个字母大写。

你将使用布尔值(简称bools)与比较运算符一起形成条件。我们将先讨论比较运算符,然后再讨论条件。

比较运算符

比较运算符比较两个值,并求值为TrueFalse布尔值。表 3-1 列出了所有比较运算符。

**表 3-1:**比较运算符

运算符 操作
< 小于
> 大于
<= 小于或等于
>= 大于或等于
== 等于
!= 不等于

你已经了解了+-*/数学运算符。像任何运算符一样,比较运算符与值结合形成表达式,比如guessesTaken < 6

猜数字程序的第 17 行使用了小于比较运算符:

if guess < number:

我们将很快更详细地讨论if语句;现在,让我们只看一下跟在if关键字后面的表达式(guess < number部分)。这个表达式包含两个值(变量guessnumber中的值)由一个运算符(<,或小于号)连接而成。

使用条件检查 True 或 False

条件是一个将两个值与比较运算符(如<>)组合的表达式,并求值为布尔值。条件只是另一个名称,用于求值为TrueFalse的表达式。我们使用条件的一个地方是在if语句中。

例如,第 17 行的条件guess < number询问:“guess中存储的值是否小于number中存储的值?”如果是,则条件求值为True。如果不是,则条件求值为False

假设guess存储整数10number存储整数16。因为10小于16,所以这个条件求值为布尔值True。评估如下所示:

尝试布尔值、比较运算符和条件

在交互式 shell 中输入以下表达式以查看它们的布尔结果:

>>> 0 < 6
True
>>> 6 < 0
False

条件0 < 6返回布尔值True,因为数字0小于数字6。但是因为6不小于0,所以条件6 < 0求值为False

请注意,10 < 10求值为False,因为数字10不小于数字10

>>> 10 < 10
False

这些值是相同的。如果 Alice 和 Bob 的身高相同,你不会说 Alice 比 Bob 高或 Alice 比 Bob 矮。这两个陈述都是错误的。

现在将这些表达式输入到交互式 shell 中:

>>> 10 == 10
True
>>> 10 == 11
False
>>> 11 == 10
False
>>> 10 != 10
False

在这个例子中,10等于10,所以10 == 10求值为True。但10不等于11,所以10 == 11False。即使顺序颠倒,11仍然不等于10,所以11 == 10False。最后,10等于10,所以10 != 10False

您还可以使用比较运算符评估字符串表达式:

>>> 'Hello' == 'Hello'
True
>>> 'Goodbye' != 'Hello'
True
>>> 'Hello' == 'HELLO'
False

'Hello'等于'Hello',所以'Hello' == 'Hello'True'Goodbye'不等于'Hello',所以'Goodbye' != 'Hello'也是True

请注意,最后一行求值为False。在 Python 中,大写和小写字母不相同,所以'Hello'不等于'HELLO'

字符串和整数值永远不会相等。例如,将以下内容输入到交互式 shell 中:

>>> 42 == 'Hello'
False
>>> 42 != '42'
True

在第一个例子中,42是一个整数,'Hello'是一个字符串,所以这些值不相等,表达式求值为False。在第二个例子中,字符串'42'仍然不是一个整数,所以表达式“整数42不等于字符串'42'”求值为True

=和==之间的区别

要小心不要混淆赋值运算符=和等于比较运算符==。等号=用于赋值语句将值存储到变量中,而双等号==用于表达式,以查看两个值是否相等。很容易在本意使用一个时意外使用另一个。

也许有助于记住等于比较运算符==和不等于比较运算符!=都有两个字符。

if 语句

第 17 行是一个if语句:

if guess < number:
        print('Your guess is too low.') # Eight spaces in front of "print"

if语句后面的代码块将在if语句的条件求值为True时运行。如果条件为False,则跳过if块中的代码。使用if语句,您可以使程序仅在需要时运行特定代码。

第 17 行检查玩家的猜测是否小于计算机的秘密数字。如果是,则执行移动到第 18 行的if块内,并打印一条消息告诉玩家他们的猜测太低了。

第 20 行检查玩家的猜测是否大于秘密数字:

if guess > number:
        print('Your guess is too high.')

如果这个条件为True,那么print()函数调用会告诉玩家他们的猜测太高。

使用 break 语句提前离开循环

第 23 行的if语句检查玩家猜测的数字是否等于秘密数字。如果是,程序会执行第 24 行的break语句:

if guess == number:
        break

break语句告诉执行立即跳出for块,到达for块结束后的第一行。break语句只在循环内找到,比如在for块中。

检查玩家是否赢了

for块在没有缩进的下一行代码结束,即第 26 行:

if guess == number:

执行离开for块,要么是因为它已经循环了六次(当玩家猜错次数用尽时),要么是因为第 24 行的break语句已经执行(当玩家猜对了数字)。

第 26 行检查玩家是否猜对了。如果是,执行进入第 27 行的if块:

guessesTaken = str(guessesTaken + 1)
    print('Good job, ' + myName + '! You guessed my number in ' +
          guessesTaken + ' guesses!')

第 27 行和第 28 行只有在第 26 行的if语句的条件为True时执行(也就是说,如果玩家正确猜到了计算机的数字)。

第 27 行调用str()函数,它返回guessesTaken + 1的字符串形式(因为range函数从 0 到 5 而不是从 1 到 6)。第 28 行连接字符串,告诉玩家他们赢了多少次猜测。只有字符串值可以连接到其他字符串。这就是为什么第 27 行必须将guessesTaken + 1更改为字符串形式。否则,尝试将字符串与整数连接会导致 Python 显示错误。

检查玩家是否输了

如果玩家猜错次数用尽,执行将到达这行代码:

if guess != number:

第 30 行使用不等于比较运算符!=来检查玩家的最后一次猜测是否不等于秘密数字。如果这个条件计算为True,执行将进入第 31 行的if块。

第 31 行和第 32 行在if块内,只有在第 30 行的条件为True时执行:

number = str(number)
    print('Nope. The number I was thinking of was ' + number + '.')

在这个块中,程序告诉玩家秘密数字是多少。这需要连接字符串,但number存储的是一个整数值。第 31 行用一个字符串覆盖number,这样它就可以与第 32 行的'Nope. The number I was thinking of was ''.'字符串连接起来。

此时,执行已经到达代码的末尾,程序终止。恭喜!你刚刚编写了你的第一个真正的游戏!

你可以通过改变玩家获得的猜测次数来调整游戏的难度。要让玩家只有四次猜测,改变第 12 行的代码:

for guessesTaken in range(4):

通过将4传递给range(),你确保循环内的代码只运行四次,而不是六次。这会使游戏变得更加困难。要使游戏变得更容易,传递一个更大的整数给range()函数调用。这将导致循环运行几次更多,并接受更多玩家的猜测。

摘要

编程只是为程序编写代码的行为,也就是创建可以由计算机执行的程序。

当你看到有人使用计算机程序(例如,玩你的猜数字游戏),你只会看到一些文本出现在屏幕上。程序根据它的指令和玩家用键盘输入的文本(程序的输入)决定在屏幕上显示什么文本(程序的输出)。程序只是一系列根据用户输入进行操作的指令。

有几种指令:

  • 表达式是由运算符连接的值。表达式都被计算为单个值。例如,2 + 2计算为4'Hello' + ' ' + 'World'计算为'Hello World'。当表达式紧邻iffor关键字时,你也可以称它们为条件
  • 赋值语句将值存储在变量中,以便以后在程序中记住这些值。
  • ifforbreak语句是流程控制语句,可以使执行跳过指令、循环执行指令或跳出循环。函数调用也通过跳转到函数内部的指令来改变执行流程。
  • print()input()函数在屏幕上显示文本并从键盘获取文本。处理程序的输入输出的指令称为I/O(发音为eye oh)。

就是这样 - 就这四样东西。当然,关于这四种类型的指令还有许多细节需要学习。在后面的章节中,你将了解更多的数据类型和运算符,更多的流程控制语句,以及许多其他与 Python 一起使用的函数。除了文本之外,还有不同类型的 I/O,比如鼠标输入和声音和图形输出。

四、笑话程序

原文:inventwithpython.com/invent4thed/chapter4.html

译者:飞龙

协议:CC BY-NC-SA 4.0

本章的程序向用户讲述了一些笑话,并演示了更高级的使用字符串与print()函数的方法。本书中的大多数游戏都将使用简单的文本进行输入和输出。输入是用户在键盘上输入的文本,输出是显示在屏幕上的文本。

本章涵盖的主题

  • 转义字符
  • 使用单引号和双引号表示字符串
  • 使用print()end关键字参数来跳过换行

你已经学会了如何使用print()函数显示简单的文本输出。现在让我们更深入地了解 Python 中字符串和print()的工作原理。

笑话示例运行

当用户运行笑话程序时,他们看到的是这样的:

What do you get when you cross a snowman with a vampire?
Frostbite!
What do dentists call an astronaut's cavity?
A black hole!
Knock knock.
Who's there?
Interrupting cow.
Interrupting cow wh-MOO!

笑话的源代码

通过点击文件新建窗口,打开一个新的文件编辑器窗口。在出现的空白窗口中,输入源代码并将其保存为jokes.py。然后按 F5 运行程序。

如果输入这段代码后出现错误,请使用在线 diff 工具将你输入的代码与书中的代码进行比较,网址为www.nostarch.com/inventwithpython#diff

jokes.py

print('What do you get when you cross a snowman with a vampire?')
input()
print('Frostbite!')
print()
print('What do dentists call an astronaut\'s cavity?')
input()
print('A black hole!')
print()
print('Knock knock.')
input()
print("Who's there?")
input()
print('Interrupting cow.')
input()
print('Interrupting cow wh', end='')
print('-MOO!')

代码的工作原理

让我们先看一下代码的前四行:

print('What do you get when you cross a snowman with a vampire?')
input()
print('Frostbite!')
print()

第 1 行和第 3 行使用print()函数调用来询问并给出第一个笑话的答案。你不希望用户立即看到笑话的结尾,所以在第一个print()后有一个对input()函数的调用。用户会看到笑话,按 ENTER 键,然后看到结尾。

用户仍然可以输入一个字符串并按 ENTER 键,但是这个返回的字符串并没有被存储在任何变量中。程序会忘记它并移到下一行代码。

最后一个print()函数调用没有字符串参数。这告诉程序只打印一个空行。空行有助于保持文本不显得拥挤。

转义字符

第 5 到 8 行打印了下一个笑话的问题和答案:

print('What do dentists call an astronaut\'s cavity?')
input()
print('A black hole!')
print()

在第 5 行,单引号前面有一个反斜杠:\'。(请注意,\是反斜杠,/是正斜杠。)这个反斜杠告诉你它后面的字母是一个转义字符。转义字符允许你打印出在源代码中难以或不可能输入的特殊字符,比如以单引号开头和结尾的字符串值中的单引号。

在这种情况下,如果我们不包括反斜杠,astronaut\'s中的单引号会被解释为字符串的结束。但是这个引号需要作为字符串的一部分。转义的单引号告诉 Python 应该将单引号包含在字符串中。

但是如果你真的想显示一个反斜杠呢?

从你的jokes.py程序切换到交互式 shell,并输入这个print()语句:

>>> print('They flew away in a green\teal helicopter.')
They flew away in a green    eal helicopter.

这条指令没有打印出反斜杠,因为teal中的t被解释为转义字符,因为它在反斜杠后面。\t模拟了在键盘上按下 TAB 键。

这行代码将给出正确的输出:

>>> print('They flew away in a green\\teal helicopter.')
They flew away in a green\teal helicopter.

这样\\就是一个反斜杠字符,而没有\t被解释为 TAB。

表 4-1 是 Python 中一些转义字符的列表,包括\n,这是换行转义字符,你之前用过。

**表 4-1:**转义字符

转义字符 实际打印的内容
\\ 反斜杠(\
\' 单引号('
\" 双引号("
\n 换行
\t 制表符

Python 中还有一些其他转义字符,但这些字符是你创建游戏时最有可能需要的字符。

单引号和双引号

当我们还在交互式 shell 中时,让我们更仔细地看一下引号。在 Python 中,字符串并不总是要用单引号括起来的。你也可以用双引号括起来。这两行打印的是相同的内容:

>>> print('Hello world')
Hello world
>>> print("Hello world")
Hello world

但你不能混合使用引号。这行会报错,因为它同时使用了两种引号类型:

>>> print('Hello world")
SyntaxError: EOL while scanning single-quoted string

我喜欢使用单引号,这样就不必按住 SHIFT 键来输入它们。它们更容易输入,而 Python 也无所谓。

另外,请注意,就像你需要在单引号括起的字符串中使用\'来表示单引号一样,你需要在双引号括起的字符串中使用\"来表示双引号。看这个例子:

>>> print('I asked to borrow Abe\'s car for a week. He said, "Sure."')
I asked to borrow Abe's car for a week. He said, "Sure."

你使用单引号来括起字符串,因此你需要在Abe\'s的单引号前添加反斜杠。但"Sure."中的双引号不需要反斜杠。Python 解释器足够聪明,知道如果一个字符串以一种引号开始,另一种引号并不意味着字符串结束。

现在看另一个例子:

>>> print("She said, \"I can't believe you let them borrow your car.\"")
She said, "I can't believe you let them borrow your car."

字符串用双引号括起来,因此你需要为字符串中的所有双引号添加反斜杠。在can't中不需要转义单引号。

总之,在单引号字符串中,你不需要转义双引号,但需要转义单引号;在双引号字符串中,你不需要转义单引号,但需要转义双引号。

print()函数的 end 关键字参数

现在让我们回到jokes.py,看一下第 9 到 16 行:

print('Knock knock.')
input()
print("Who's there?")
input()
print('Interrupting cow.')
input()
print('Interrupting cow wh', end='')
print('-MOO!')

你注意到了第 15 行print()函数的第二个参数吗?通常,print()会在打印的字符串末尾添加一个换行符。这就是为什么空的print()函数会打印一个换行符。但print()可以选择性地有第二个参数:end

记住,参数是函数调用中传递的值。传递给print()的空字符串称为关键字参数end=''中的end称为关键字参数。要将关键字参数传递给这个关键字参数,你必须在它之前输入end=

当我们运行这部分代码时,输出是

Knock knock.
Who's there?
Interrupting cow.
Interrupting cow wh-MOO!

因为我们将空字符串传递给了end参数,print()函数会添加一个空字符串而不是添加一个换行符。这就是为什么'-MOO!'出现在前一行的旁边,而不是在自己的一行上。在打印'Interrupting cow wh'字符串后没有换行符。

总结

本章探讨了使用print()函数的不同方式。转义字符用于在代码中使用键盘难以输入的字符。如果你想在字符串中使用特殊字符,你必须使用反斜杠转义字符\,后面跟着另一个字母表示特殊字符。例如,\n表示换行。如果你的特殊字符是反斜杠本身,你使用\\

print()函数会自动在字符串末尾添加一个换行符。大多数情况下,这是一个方便的快捷方式。但有时你不想要换行符。要更改这一点,你可以将空字符串作为print()end关键字参数的关键字参数传递。例如,要在屏幕上打印spam而不带换行符,你可以调用print('spam', end='')

相关文章
|
16天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
16天前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
1天前
|
机器学习/深度学习 数据挖掘 API
pymc,一个灵活的的 Python 概率编程库!
pymc,一个灵活的的 Python 概率编程库!
4 1
|
1天前
|
人工智能 算法 调度
uvloop,一个强大的 Python 异步IO编程库!
uvloop,一个强大的 Python 异步IO编程库!
10 2
|
2天前
|
机器学习/深度学习 人工智能 数据可视化
Python:探索编程之美
Python:探索编程之美
9 0
|
2天前
|
机器学习/深度学习 人工智能 数据处理
Python编程的魅力与实践
Python编程的魅力与实践
|
3天前
|
SQL 关系型数据库 MySQL
第十三章 Python数据库编程
第十三章 Python数据库编程
|
3天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
4天前
|
算法 Python
Python 一步一步教你用pyglet制作汉诺塔游戏
Python 一步一步教你用pyglet制作汉诺塔游戏
16 0
|
9天前
|
安全 数据处理 开发者
《Python 简易速速上手小册》第7章:高级 Python 编程(2024 最新版)
《Python 简易速速上手小册》第7章:高级 Python 编程(2024 最新版)
19 1