笨办法学 Python3 第五版(预览)(三)(3)https://developer.aliyun.com/article/1483443
练习 36:设计和调试
现在你已经了解了if
语句,我将给你一些关于for
循环和while
循环的规则,这将帮助你避免麻烦。我还会给你一些关于调试的提示,这样你就可以找出程序中的问题。最后,你将设计一个类似于上一个练习但有些不同的小游戏。
从想法到可运行的代码
有一个简单的过程任何人都可以遵循,将你的想法转化为代码。这不是唯一的过程,但对许多人来说效果很好。在你开发自己的个人过程之前,使用这个过程。
- 以你理解的任何形式将你的想法表达出来。你是作家吗?那就写一篇关于你的想法的文章。你是艺术家或设计师吗?那就画出用户界面。你喜欢图表吗?看看序列图,这是编程中最有用的图之一。
- 为你的代码创建一个文件。是的,信不信由你,这是一个重要的步骤,大多数人都会遇到困难。如果你想不出一个名字,就随便挑一个吧。
- 用简单的英语(或者你最容易理解的语言)写下你的想法的描述作为注释。
- 从顶部开始,将第一个注释转换为“伪代码”,这有点像 Python,但你不用在意语法。
- 将那个“伪代码”转换为真正的 Python 代码,并不断运行你的文件,直到这段代码实现了你的注释所说的。
- 重复这个过程,直到你将所有的注释转换为 Python 代码。
- 退一步,审查你的代码,然后删除它。你不必一直这样做,但如果你养成丢弃第一个版本的习惯,你将获得两个好处:
a. 你的第二个版本几乎总是比第一个版本好。
b. 你向自己确认这不仅仅是愚蠢的运气。你确实能编写代码。这有助于应对冒名顶替综合症和增强自信。
让我们用一个简单的问题“创建一个简单的华氏度到摄氏度转换器”来做一个例子。第一步,我会写出我对转换的了解:
C 等于 (F - 32 ) / 1.8。我应该询问用户输入 F,然后打印出 C。
一个非常基本的数学公式是理解问题的简单方法。第二步,我写下描述我的代码应该做什么的注释:
1 # ask the user for the F 2 # convert it to a float() 3 # C = (F - 32) / 1.8 4 # print C to the user
一旦我有了这个,我会用伪代码“填空”。我只会做第一行,这样你就可以完成这个:
1 # ask the user for the F 2 F = input(?) 3 4 # convert it to a float() 5 # C = (F - 32) / 1.8 6 # print C to the user
注意,我故意懒惰,没有正确地编写语法,这就是伪代码的要点。一旦我有了这个,就将其转换为正确的 Python 代码:
1 # ask the user for the F 2 F = input("C? ") 3 4 # convert it to a float() 5 # C = (F - 32) / 1.8 6 # print C to the user
运行它! 你应该不断地运行你的代码。如果你输入了超过几行,只需删除它们,重新开始。这样会容易得多。
现在这些行起作用了,我继续下一个注释并重复这个过程,直到我将所有的注释转换成 Python。当我的脚本最终工作时,我会删除它并使用我所知道的重新编写它。也许这一次我直接写 Python,或者我再次重复这个过程。这样做会让我确认自己实际上是可以做到的。这不仅仅是愚蠢的运气。
这是一个专业的过程吗?
你可能会认为这个过程不实用或不专业。我认为,当你刚开始时,你需要不同于那些编程时间很长的人所需的工具。我可以坐下来想一个点子然后编码,但我已经从事专业编程的时间比你活了的时间还长。然而,在我的脑海中,这基本上是我遵循的过程。我只是在脑海中迅速地做这个过程,而你必须在外部练习直到内化。
当我卡住或者在学习一门新语言时,我会使用这个过程。如果我不懂一门语言但知道我想做什么,那么我通常可以写注释然后慢慢将其转换为代码,这也教会我那种语言。我和你之间唯一的区别是,由于多年的训练,我做得更快。
关于“X/Y”非问题
一些专业人士声称,这个过程会让学生患上一种奇怪的疾病,称为“X/Y 问题”。他们将 X/Y 问题描述为“有人想做 X,但只知道如何做 Y,所以他们请求帮助如何做 Y。” X/Y 问题的问题在于它批评了那些简单学习编程的人,并没有提出解决方案。对于“X/Y 问题的讨厌者”,解决方案似乎是“已经知道答案”,因为如果他们知道如何做 X,他们就不会去烦恼 Y。这种信念的虚伪之处在于所有讨厌这种问题的人都经历过这个阶段,提出过这些完全相同的“X/Y”问题。
另一个问题是,他们在责备你的糟糕文档。经典的例子来自 X/Y 问题的原始描述:
1 <n00b> How can I echo the last three characters in a filename? 2 3 <feline> If they're in a variable: echo ${foo: -3} 4 <feline> Why 3 characters? What do you REALLY want? 5 <feline> Do you want the extension? 6 7 <n00b> Yes. 8 9 <feline> Then ASK FOR WHAT YOU WANT! 10 <feline> There's no guarantee that every filename will 11 have a three-letter extension, 12 <feline> so blindly grabbing three characters does not 13 solve the problem. 14 <feline> echo ${foo##*.}
首先,这个feline
人实际上在一个专门回答问题的 IRC 频道里大声责骂某人提问。“要求你想要的东西!”第二个问题是,他们的解决方案是我——一个有几十年经验的 bash 和 Linux 专业人士——每次都要查找的东西。这是 bash 中最糟糕文档化、最不可用的功能之一。一个初学者如何能预先知道他们应该使用一些复杂的“dollar brace name pound pound asterisk dot brace”操作?如果在线有简单的文档解释如何做这个操作,这个人很可能不会提出这个问题。如果 bash 实际上有一个基本功能来执行这个每个人都需要的非常常见的操作,那将更好。
当涉及“X/Y 问题”时,这实际上只是一个借口,用来责骂初学者是初学者。每个声称讨厌这个问题的人要么根本不写代码,要么绝对在学习编程时确实做过这样的事情。这就是学习编程的方式。您遇到问题并通过学习如何实现解决方案来摸索解决方案。因此,如果遇到像这样的人,只需忽略他们。他们只是借口找个人发火并感觉自己更优越。
此外,您会注意到在上一个对话中,没有一个人要求看代码。如果只是展示了他们的代码,那么
就可以推荐更好的方法来解决问题。问题解决了。我是说,假设
实际上能够编写代码,而不只是在 IRC 中等待着攻击毫无戒备的初学者提问。
if 语句规则
- 每个
if
语句必须有一个else
。 - 如果
else
部分永远不应该运行,因为这没有意义,那么你必须在else
中使用一个 die 函数,打印出错误消息并终止程序,就像我们在之前的练习中所做的那样。这将找到许多错误。 - 永远不要嵌套超过两层的
if
语句,并始终尝试将其保持一层。 - 将
if
语句视为段落,其中每个if-elif-else
组合就像一组句子。在其前后放置空行。 - 您的布尔测试应该简单。如果它们复杂,将它们的计算移到函数中的变量中,并为变量使用一个好的名称。
如果您遵循这些简单的规则,您将开始写出比大多数程序员更好的代码。回到上一个练习,看看我是否遵循了所有这些规则。如果没有,请纠正我的错误。
警告!
在现实生活中永远不要成为规则的奴隶。在训练过程中,您需要遵循这些规则以增强思维能力,但在现实生活中,有时这些规则只是愚蠢的。如果您认为某个规则很愚蠢,请尝试不使用它。
循环规则
- 仅在需要永久循环时才使用
while
循环,这意味着可能永远不会用到。这仅适用于 Python;其他语言不同。 - 对于所有其他类型的循环,请使用
for
循环,特别是在需要循环的事物数量是固定或有限的情况下。
调试提示
- 不要使用“调试器”。调试器就像对生病的人进行全身扫描一样。您不会得到任何具体有用的信息,而会发现许多无用且令人困惑的信息。
- 调试程序的最佳方法是使用
print
打印出程序中变量的值,以查看它们出错的位置。 - 确保程序的各个部分在编写时能够正常工作。不要在尝试运行之前编写大量的代码文件。少写一点,运行一点,修复一点。
作业
现在编写一个类似于我在上一个练习中创建的游戏。它可以是你想要的任何类型的游戏,但风格相同。花一周的时间让它尽可能有趣。在学习练习中,尽可能使用列表、函数和模块(还记得练习 13 中的那些吗?),并找到尽可能多的新的 Python 片段来使游戏运行。
在开始编码之前,你必须为你的游戏绘制一张地图。在编码之前,先在纸上创建玩家必须经过的房间、怪物和陷阱。
有了地图后,尝试着编写代码。如果在地图中发现问题,那就调整它,使代码与之匹配。
在软件开发中,最好的方法是像这样分成小块:
- 在一张纸上或一张索引卡上,写下你需要完成的任务列表,以完成软件开发。这就是你的待办事项清单。
- 从你的清单中选择最容易的任务。
- 在你的源文件中写下英文注释,作为你在代码中如何完成这个任务的指南。
- 在英文注释下面写一些代码。
- 快速运行你的脚本,看看代码是否有效。
- 保持在写一些代码、运行测试并修复直到它有效的循环中工作。
- 将这个任务从你的清单上划掉,然后选择下一个最容易的任务并重复。
这个过程将帮助你以一种系统和一致的方式来开发软件。在工作时,通过删除你实际不需要的任务并添加你需要的任务来更新你的清单。
练习 37:符号复习
现在是时候复习你所知道的符号和 Python 关键字,并尝试在接下来的几节课中学习更多。我已经列出了所有重要的 Python 符号和关键字。
在这节课中,首先尝试从记忆中写出每个关键字的作用。接下来,在网上搜索它们,看看它们真正的作用。这可能很困难,因为有些很难搜索,但无论如何都要尝试。
如果你从记忆中记错了其中一个,就制作一张正确定义的索引卡,尝试“纠正”你的记忆。
最后,在一个小的 Python 程序中使用这些中的每一个,或者尽可能多地完成。目标是找出符号的作用,确保你理解正确,如果不正确就纠正,然后使用它来牢记。
关键字
数据类型
对于数据类型,写出每种数据类型的组成部分。例如,对于字符串,写出如何创建一个字符串。对于数字,写出一些数字。
字符串转义序列
对于字符串转义序列,将它们用在字符串中,确保它们执行你认为的操作。
旧式字符串格式
对于字符串格式也是一样:在一些字符串中使用它们,以了解它们的作用。
旧版 Python 2 代码使用这些格式化字符来实现 f-strings 的功能。尝试它们作为替代方案。
运算符
其中一些可能对你来说很陌生,但无论如何都要查找它们。找出它们的作用,如果你仍然无法弄清楚,就留到以后再看。
大约花一周的时间,但如果你更快完成,那就太好了。重点是尝试覆盖所有这些符号,并确保它们牢记在你的脑海中。同样重要的是找出你不知道的东西,这样你就可以以后修复它。
阅读代码
现在找一些 Python 代码来阅读。你应该阅读任何你能找到的 Python 代码,并尝试窃取你发现的想法。你实际上应该有足够的知识来阅读,但也许不理解代码的作用。这节课教你如何应用你学到的东西来理解别人的代码。
首先,打印出你想要理解的代码。是的,打印出来,因为你的眼睛和大脑更习惯于阅读纸张而不是电脑屏幕。确保每次打印几页。
其次,浏览你的打印输出,并对以下内容做笔记:
- 函数及其作用。
- 每个变量首次被赋值的地方。
- 程序中不同部分中具有相同名称的任何变量。这些以后可能会有麻烦。
- 没有
else
子句的if
语句。它们正确吗? - 任何可能不会结束的
while
循环。 - 任何你因为任何原因无法理解的代码部分。
第三,一旦你标记了所有这些,尝试通过写注释来向自己解释。解释函数,它们如何被使用,涉及哪些变量以及你可以找出这段代码的任何内容。
最后,在所有困难的部分,逐行追踪每个变量的值,逐个函数地。实际上,再做一份打印输出,并在边缘写下你需要“追踪”的每个变量的值。
一旦你对代码的功能有了很好的理解,回到电脑上再次阅读它,看看是否能发现新的东西。继续找到更多的代码并这样做,直到你不再需要打印输出为止。
学习练习
- 找出“流程图”是什么,并画几个。
- 如果你在阅读代码时发现错误,请尝试修复它们,并将更改发送给作者。
- 当你不使用纸张时的另一种技巧是在代码中用
#
注释来记录你的笔记。有时,这些注释可能成为实际的注释,帮助下一个人。
常见学生问题
我该如何在网上搜索这些内容? 只需在你想要查找的任何内容前加上“python3”。例如,要查找yield
,搜索python3 yield
。