原标题:30分钟学会用Python编写简单程序
参与文末每日话题讨论,赠送异步新书
异步图书君
学习目标
知道有序的软件开发过程的步骤。
了解遵循输入、处理、输出(IPO)模式的程序,并能够以简单的方式修改它们。
了解构成有效Python标识符和表达式的规则。
能够理解和编写Python语句,将信息输出到屏幕,为变量赋值,获取通过键盘输入的信息,并执行计数循环。 软件开发过程
运行已经编写的程序很容易。较难的部分实际上是先得到一个程序。计算机是非常实在的,必须告诉它们要做什么,直至最后的细节。编写大型程序是一项艰巨的挑战。如果没有系统的方法,几乎是不可能的。
创建程序的过程通常被分成几个阶段,依据是每个阶段中产生的信息。简而言之,你应该做以下工作。
分析问题 确定要解决的问题是什么。尝试尽可能多地了解它。除非真的知道问题是什么,否则就不能开始解决它。
确定规格说明 准确描述程序将做什么。此时,你不必担心程序"怎么做”,而是要确定它"做什么”。对于简单程序,这包括仔细描述程序的输入和输出是什么以及它们的相互关系。
创建设计 规划程序的总体结构。这是描述程序怎么做的地方。主要任务是设计算法来满足规格说明。
实现设计 将设计翻译成计算机语言并放入计算机。在本书中,我们将算法实现为Python程序。
测试/调试程序 试用你的程序,看看它是否按预期工作。如果有任何错误(通常称为"缺陷”),那么你应该回去修复它们。定位和修复错误的过程称为"调试”程序。在调试阶段,你的目标是找到错误,所以应该尝试你能想到的"打破”程序的一切可能。记住这句老格言:"没有什么能防住人犯傻,因为傻子太聪明了。”
维护程序 继续根据用户的需求开发该程序。大多数程序从来没有真正完成,它们在多年的使用中不断演进。 示例程序:温度转换器
让我们通过一个真实世界的简单例子,来体验软件开发过程的步骤,其中涉及一个虚构的计算机科学学生Susan Computewell。
Susan正在德国学习一年。她对语言没有任何问题,因为她能流利地使用许多语言(包括Python)。她的问题是,很难在早上弄清楚温度从而知道当天该穿什么衣服。Susan每天早上听天气报告,但温度以摄氏度给出,她习惯了华氏度。
幸运的是,Susan有办法解决这个问题。作为计算机科学专业的学生,她去任何地方总是带着她的笔记本计算机。她认为计算机程序可能会帮助她。
Susan开始分析她的问题。在这个例子中,问题很清楚:无线电广播员用摄氏度报气温,但Susan只能理解华氏温度。
接下来,Susan考虑可能帮助她的程序的规格说明。输入应该是什么?她决定程序将允许她输入摄氏温度。输出呢?程序将显示转换后的华氏温度。现在她需要指定输出与输入的确切关系。
苏珊快速估算了一下。她知道0摄氏度(冰点)等于32华氏度,100摄氏度(沸点)等于212华氏度。有了这个信息,她计算出华氏度与摄氏度的比率为(212−32)/(100−0) = (180/100) = 9/5。使用F表示华氏温度,C表示摄氏温度,转换公式的形式为F = (9/5)C + k,其中k为某个常数。代入0和32分别作为C和F,Susan立即得到k = 32。所以最后的关系公式是F = (9/5)C + 32。这作为规格说明似乎足够了。
请注意,这描述了能够解决这个问题的许多可能程序中的一个。如果Susan有人工智能(AI)领域的背景,她可能会考虑写一个程序,用语音识别算法实际收听收音机播音员,获得当前的温度。对于输出,她可以让计算机控制机器人进入她的衣柜,并根据转换后的温度选择适当的服装。这将是一个更有野心的项目,一点也不夸张!
当然,机器人程序也会解决问题分析中识别的问题。规格说明的目的,是准确地决定这个特定的程序要做什么,从而解决一个问题。Susan知道,最好是先弄清楚她希望构建什么,而不是一头钻进去开始编程。
Susan现在准备为她的问题设计一个算法。她马上意识到这是一个简单算法,遵循标准模式"输入、处理、输出”(IPO)。她的程序将提示用户输入一些信息(摄氏温度),处理它,产生华氏温度,然后在计算机屏幕上显示结果,作为输出。
Susan可以用一种计算机语言来写她的算法。然而,正式将它写出来需要相当的精度,这常常会扼杀开发算法的创造性过程。作为替代,她用"伪代码”编写算法。伪代码只是精确的英语,描述了程序做的事。这意味着既可以交流算法,又不必让大脑承担额外的开销,正确写出某种特定编程语言的细节。
下面是Susan的完整算法:
输入摄氏度温度(称为celsius)计算华氏度为(9/5)celsius + 32输出华氏度
下一步是将此设计转换为Python程序。这很直接,因为算法的每一行都变成了相应的Python代码行。
# convert.py# A program to convert Celsius temps to Fahrenheit# by: Susan Computewelldef main(): celsius = eval(input(What is the Celsius temperature?)) fahrenheit = 9/5 * celsius + 32 print(The temperature is, fahrenheit, degrees Fahrenheit.)main()
看看你是否能弄清楚这个程序的每一行做了什么。如果一些部分不是很清楚,也不要担心,下一节将详细讨论。
完成程序后,Susan测试它,看看它工作得如何。她使用她知道正确答案的输入。下面是两个测试的输出:
What is the Celsius temperature? 0The temperature is 32.0 degrees Fahrenheit.What is the Celsius temperature? 100The temperature is 212.0 degrees Fahrenheit.
你可以看到,Susan用值0和100来测试她的程序。看起来不错,她对解决方案感到满意。她特别高兴的是,似乎没有必要调试(这很不寻常)。 程序要素
既然已经知道了编程过程,你就"几乎”准备好开始自己编写程序了。在此之前,你需要更完整的基础,了解Python的基本知识。接下来的几节将讨论一些技术细节,这对编写正确程序至关重要。这种材料看起来有点乏味,但你必须掌握这些基础,然后再进入更有趣的领域。 1 名称
你已经看到,名称是编程的重要组成部分。我们为模块命名(例如convert),也为模块中的函数命名(例如main)。变量用于为值命名(例如celsius和fahrenheit)。从技术上讲,所有这些名称都称为"标识符”。Python对标识符的构成有一些规则。每个标识符必须以字母或下划线("_”字符)开头,后跟字母、数字或下划线的任意序列。这意味着单个标识符不能包含任何空格。
根据上述规则,以下都是Python中的合法名称:
xcelsiusspamspam2SpamAndEggsSpam_and_Eggs
标识符区分大小写,因此对Python来说,spam、Spam、sPam和SPAM是不同的名称。在大多数情况下,程序员可以自由选择符合这些规则的任何名称。好的程序员总是试图选择一些名字,它们能描述被命名的东西。
需要注意一件重要的事情:一些标识符是Python本身的一部分。这些名称称为"保留字”或"关键字”,不能用作普通标识符。Python关键字的完整列表如表1所列。
表1 Python关键字
False
class
finally
is
return
None
continue
for
lambda
try
True
def
from
nonlocal
while
and
del
global
not
with
as
elif
if
or
yield
assert
else
import
pass
break
except
in
raise
Python还包括相当多的内置函数,例如我们用过的print函数。虽然在技术上可以将内置的函数名称标识符用于其他目的,但这通常是一个"非常糟糕”的主意。例如,如果你重新定义print的含义,那么就无法再打印信息。你也会让所有阅读程序的Python程序员感到非常困惑,他们预期print指的是内置函数。内置函数的完整列表可在附录A中找到。 2 表达式
程序操作数据。到目前为止,我们已经在示例程序中看到了数字和文本两种不同类型的数据。我们将在后面的节中详细讨论这些不同的数据类型。现在,你只需要记住,所有的数据必须以一些数字格式存储在计算机上,不同类型的数据以不同的方式存储。
产生或计算新数据值的程序代码片段称为"表达式”。最简单的表达式是字面量。字面量用于表示特定值。在chaos.py中,你可以找到数字3.9和1。convert.py程序包含9、5和32。这些都是数字字面量的例子,它们的含义显而易见:32就是代表32(数字32)。
我们的程序还以一些简单的方式处理文本数据。计算机科学家将文本数据称为"字符串”。你可以将字符串视为可打印字符的序列。Python中通过将字符括在引号()中来表示字符串字面量。如果你回头看看我们的示例程序,可以发现一些字符串字面量,例如Hello和Enter a number between 0 and 1:。这些字面量产生的字符串包含引号内的字符。请注意,引号本身不是字符串的一部分。它们只是告诉Python创建一个字符串的机制。
将表达式转换为基础数据类型的过程称为"求值”。在Python shell中键入表达式时,shell会计算表达式并打印出结果的文本表示。请考虑以下简短的交互:
3232 Hello'Hello' 32'32'
请注意,当shell显示字符串的值时,它将字符序列放在单引号中。这样让我们知道该值实际上是文本而不是数字(或其他数据类型)。在最后一次交互中,我们看到表达式32产生一个字符串,而不是一个数字。在这种情况下,Python实际上是存储字符"3”和"2”,而不是数字32的表示。如果你现在不太明白,不要太担心。我们在后面的节中讨论这些数据类型时,你的理解就会变得更加清晰。
一个简单的标识符也可以是一个表达式。我们使用标识符作为变量来给名字赋值。当标识符作为表达式出现时,它的值会被取出,作为表达式的结果。下面是与Python解释器的交互,展示了变量作为表达式:
x = 5 x5 print(x)5 print(spam)Traceback (most recent call last): File stdin, line 1, in moduleNameError: name 'spam' is not defined
首先,变量x被赋值为5(使用数字字面量5)。在第二行交互中,我们要求Python对表达式x求值。作为响应,Python shell打印出5,这是刚才赋给x的值。当然,如果我们明确要求Python用print语句打印x,也会得到相同的结果。最后一个交互展示了如果尝试使用未赋值的变量,会发生什么。Python找不到值,所以它报告NameError。这说明没有该名称的值。这里的要点是,变量总是必须赋一个值,然后才能在表达式中使用。
较复杂、较有趣的表达式可以通过组合较简单的表达式和操作符来构造。对于数字,Python提供了一组标准的数学运算:加法、减法、乘法、除法和乘方。相应的Python运算符为"+”"-”"*”"/”和"**”。下面是一些来自chaos.py和convert.py的复杂表达式的例子:
3.9 * x * (1 - x)9/5 * celsius + 32
空格在表达式中没有作用。最后一个表达式如果写成9/5*celsius+32,结果完全相同。通常,在表达式中加一些空格让它更容易阅读,是个好方法。
Python的数学运算符遵循的优先级和结合律,与你在数学课上学到的相同,包括使用括号来改变求值的顺序。在自己的程序中构建复杂表达式应该没什么困难。请记住,只有圆括号在数字表达式中是允许的。如果需要,可以嵌套使用它们,创建如下的表达式:
((x1 - x2) / 2*n) + (spam / k**3)
顺便说一句,Python还提供了字符串的运算符。例如,可以"加”字符串。
Bat + man'Batman'
这被称为"连接”。如你所见,效果是创建一个新的字符串,把两个字符串"粘”在一起。 3 输出语句
既然有了基本的构建块(标识符和表达式),你就可以更完整地描述各种Python语句。 你已经知道信息可以使用Python的内置函数print在屏幕上显示。到目前为止,我们已经看了几个例子,但我还没有详细解释打印功能。像所有的编程语言一样,Python对每个语句的语法(形式)和语义(意义)有一套精确的规则。计算机科学家已经开发了复杂的符号表示法,称为"元语言”,用于描述编程语言。在本书中,我们将依靠一个简单的模板符号表示法来说明各种语句的语法。
因为print是一个内置函数,所以print语句与任何其他函数调用具有相同的一般形式。我们键入函数名print,后面带上括号中列出的参数。下面是用我们的模板符号时print语句看起来的样子:
print(expr, expr, ..., expr)print()
这两个模板展示了两种形式的print语句。第一个表示print语句可以包含函数名print,后面带上带括号的表达式序列,用逗号分隔。模板中的尖括号符号()用于表示由Python代码的其他片段填充的"槽”。括号内的名称表示缺少什么,expr表示一个表达式。省略号("...”)表示不确定的序列(在这个例子中是表达式)。你实际上不会输入圆点。第二个版本的print语句表明,不打印任何表达式的print也是合法的。
就语义而言,print语句以文本形式显示信息。所有提供的表达式都从左到右求值,结果值以从左到右的方式显示在输出行上。默认情况下,在显示的值之间放置一个空格字符。作为示例,下面print语句的序列:
print(3+4)print(3, 4, 3 + 4)print()print(The answer is, 3 + 4)
产生的输出为:
73 4 7The answer is 7
最后一个语句说明了,字符串字面量表达式如何经常在print语句使用,作为标记输出的方便方法。
注意,连续的print语句通常显示在屏幕的不同行上。空print(无参数)生成空行输出。在背后,真正发生的是,在打印所有提供的表达式之后,print函数自动附加某种结束文本。默认情况下,结束文本是表示行结束的特殊标记字符(表示为" ”)。我们可以通过包含一个附加参数显式地覆盖这个默认值,从而改变这种行为。这里使用命名参数的特殊语法,或称为"关键字”参数。
包含指定结束文本的关键字参数的print语句的模板如下:
print(expr, expr, ..., expr, end= )
命名参数的关键字是end,它使用"=”符号赋值,类似于变量赋值。注意,在模板中我已经显示其默认值,即行末字符。这是一种标准方式,用于显示在未明确指定某个其他值时,关键字参数具有的值。
print语句中的end参数有一个常见用法,即允许多个print构建单行输出。例如:
print(The answer is, end=)print(3 + 4)
产生单行输出:
The answer is 7
注意,第一个print语句的输出如何以空格( )而不是行末字符结束,第二个语句的输出紧跟在空格之后。 4 赋值语句
Python中最重要的语句之一是赋值语句。我们在前面的例子中已经看到了一些。 简单赋值
基本赋值语句具有以下形式:
variable = expr
这里variable是一个标识符,expr是一个表达式。赋值的语义是,右侧的表达式被求值,然后产生的值与左侧命名的变量相关联。
下面是我们已经看到的一些赋值:
x = 3.9 * x * (1 - x)fahrenheit = 9 / 5 * celsius + 32x = 5
变量可以多次赋值。它总是保留最新赋的值。下面的交互式Python会话展示了这一点:
myVar = 0 myVar0 myVar = 7 myVar7 myVar = myVar + 1 myVar8
最后一个赋值语句展示了如何使用变量的当前值来更新它的值。在这个例子中,我只是对以前的值加1。记住,变量的值可以改变,这就是为什么它们被称为变量的原因。
有时,将变量看作计算机内存中的一种命名的存储位置是有帮助的,我们可以在其中放入一个值。当变量更改时,旧值将被删除,并写入一个新值。图1展示了用这个模型来描绘x = x + 1的效果。这正是赋值在某些计算机语言中工作的方式。这也是查看赋值效果的一种非常简单的方式,你会在整本书中看到类似这样的图片。
图1 x = x + 1的视图,变量就像盒子
Python赋值语句实际上与"变量盒子”模型略有不同。在Python中,值可能最终放在内存中的任何位置,而变量用于引用它们。对变量赋值就像把一个黄色小粘贴便签放在值上,并说"这是x”。图2给出了一个更准确的Python赋值的效果。箭头用于显示变量引用的值。请注意,旧值不会被新值擦除,变量只需切换到引用新值。效果就像将粘贴便签从一个对象移动到另一个对象一样。这是赋值在Python中实际工作的方式,所以你会看到这样一些粘贴便签样式的图片散布在本书中。
图2 x = x + 1的(Python)视图,变量就像便签
顺便说一句,即使赋值语句不直接导致变量的旧值被擦除和覆盖,你也不必担心计算机内存中充满"被丢弃”的值。如果一个值不再被任何变量引用,它就不再有用。Python将自动从内存中清除这些值,以便空间可以用于存放新值。这就像检查你的衣柜,抛出没有粘贴便签标记的东西。实际上,这个自动内存管理的过程确实被称为"垃圾收集”。 赋值输入
输入语句的目的是从程序的用户那里获取一些信息,并存储到变量中。一些编程语言有一个特殊的语句来做到这一点。在Python中,输入是用一个赋值语句结合一个内置函数input实现的。输入语句的确切形式,取决于你希望从用户那里获取的数据类型。对于文本输入,语句如下所示:
variable = input(prompt)
这里的prompt是一个字符串表达式,用于提示用户输入。提示几乎总是一个字符串字面量(即引号内的一些文本)。
当Python遇到对input的调用时,它在屏幕上打印提示。然后,Python暂停并等待用户键入一些文本,键入完成后按Enter键。用户输入的任何东西都会存储为字符串。请考虑以下简单的交互:
name = input(Enter your name:)Enter your name: John Yaya name'John Yaya'
执行input语句导致Python打印输出提示"Enter your name:”,然后解释器暂停,等待用户输入。在这个例子中,我键入John Yaya。结果,字符串"John Yaya”被记在变量name中。对name求值将返回我键入的字符串。
如果用户输入是一个数字,我们需要形式稍复杂一点的input语句:
variable = eval(input(prompt))
这里我添加了另一个内置的Python函数eval,它"包裹”了input函数。你可能会猜到,eval是"evaluate(求值)”的缩写。在这种形式中,用户键入的文本被求值为一个表达式,以产生存储到变量中的值。举例来说,字符串"32”就变成数字32。如果回头看看示例程序,到目前为止,你会看到几个例子,我们像这样从用户那里得到了数字。
x = eval(input(Please enter a number between 0 and 1:))celsius = eval(input(What is the Celsius temperature?))
重要的是要记住,如果希望得到一个数字,而不是一些原始文本(字符串),需要对input进行eval。
如果你仔细阅读示例程序,可能会注意到所有这些提示结尾处的引号内的空格。我通常在提示的末尾放置一个空格,以便用户输入的内容不会紧接着提示开始。放上空格可以让交互更容易阅读和理解。
虽然我们的数字示例特别提示用户输入数字,但在这个例子中,用户键入的只是一个数字字面量,即一个简单的Python表达式。事实上,任何有效的表达式都是可接受的。请考虑下面与Python解释器的交互:
ans = eval(input(Enter an expression:))Enter an expression: 3 + 4 * 5 print(ans)23
这里,提示输入表达式时,用户键入"3 + 4 * 5”。Python对此表达式求值(通过eval),并将值赋给变量ans。打印时,我们看到ans的值为23,与预期一样。在某种意义上,input-eval组合就像一个延迟的表达式。示例交互产生完全相同的结果,就像我们简单地写成ans = 3 + 4 * 5一样。不同的是,表达式由用户在语句执行时提供,而不是由程序员在编程时输入。
注意:eval函数功能非常强大,也有"潜在的危险”。如本例所示,当我们对用户输入求值时,本质上是允许用户输入一部分程序。Python将尽职尽责地对他们输入的任何内容求值。了解Python的人可以利用这种能力输入恶意指令。例如,用户可以键入记录计算机上的私人信息或删除文件的表达式。在计算机安全中,这被称为"代码注入”攻击,因为攻击者将恶意代码注入正在运行的程序中。
作为一名新程序员,编程给自己个人使用,计算机安全不是很大的问题。如果你坐在一台运行Python程序的计算机前面,你可能拥有对系统的完全访问权限,并且可以找到更简单的方法来删除所有文件。然而,如果一个程序的输入来自不受信任的来源,例如来自互联网上的用户,使用eval可能是灾难性的。 同时赋值
有一个赋值语句的替代形式,允许我们同时计算几个值。它看起来像这样:
var1, var2, ..., varn = expr1, expr2, ..., exprn
这称为"同时赋值”。语义上,这告诉Python对右侧所有表达式求值,然后将这些值赋给左侧命名的相应变量。下面是一个例子:
sum, diff = x+y, x-y
这里,sum得到x和y的和,diff得到x和y的差。
这种形式的赋值初看很奇怪,但实际上非常有用。这里有一个例子:假设有两个变量x和y,你希望交换它们的值。也就是说,你希望将当前存储在x中的值存储在y中,将当前存储在y中的值存储在x中。首先,你可能认为这可以通过两个简单的赋值来完成:
x = yy = x
这不行。我们可以一步一步地跟踪这些语句的执行,看看为什么。
假设x和y开始的值是2和4。让我们检查程序的逻辑,看看变量是如何变化的。以下序列用注释描述了在执行这两个语句时变量会发生什么:
# 变量 x y# 初始值 2 4x = y# 现在是 4 4y = x# 最后是 4 4
看到第一个语句将y的值赋给x,从而修改了x的原始值吗?当我们在第二步将x的值赋给y时,最终得到了原始y值的两个副本。
完成交换的一种方法是引入一个附加变量,它暂时记住x的原始值。
temp = xx = yy = temp
让我们来看看这个序列是如何工作的。
# 变量 x y temp# 初始值 2 4 暂时无值temp = x# 2 4 2x = y# 4 4 2y = temp# 4 2 2
从x和y的最终值可以看出,在这个例子中,交换成功。
这种三变量交换的方式在其他编程语言中很常见。在Python中,同时赋值语句提供了一种优雅的选择。下面是更简单的Python等价写法:
x, y = y, x
因为赋值是同时的,所以它避免了擦除一个原始值。
同时赋值也可以用单个input从用户那里获取多个数字。请考虑下面的程序,它求出考试平均分:
# avg2.py# A simple program to average two exam scores# Illustrates use of multiple inputdef main(): print(This program computes the average of two exam scores.) score1, score2 = eval(input(Enter two scores separated by a comma:)) average = (score1 + score2) / 2 print(The average of the scores is:, average)main()
该程序提示用逗号分隔两个分数。假设用户键入86,92。input语句的效果就像进行以下赋值:
score1, score2 = 86, 92
我们已经为每个变量获得了一个值。这个例子只用了两个值,但可以扩展到任意数量的输入。
当然,我们也可以通过单独的input语句获得用户的输入:
score1 = eval(input(Enter the first score:))score2 = eval(input(Enter the second score:))
某种程度上,这可能更好,因为单独的提示对用户来说信息更准确。在这个例子中,决定采用哪种方法在很大程度上是品位问题。有时在单个input中获取多个值提供了更直观的用户接口,因此在你的工具包中,这是一项好技术。但要记住,多个值的技巧不适用于字符串(非求值)输入,如果用户键入逗号,它只是输入字符串中的一个字符。逗号仅在随后对字符串求值时,才成为分隔符。 确定循环
你已经知道,程序员用循环连续多次执行一系列语句。最简单的循环称为"确定循环”。这是会执行一定次数的循环。也就是说,在程序中循环开始时,Python就知道循环(或"迭代”)的次数。例如,前面介绍的chaos程序用了一个总是执行10次的循环:
for i in range(10): x = 3.9 * x * (1 - x) print(x)
这个特定的循环模式称为"计数循环”,它用Python的for语句构建。在详细分析这个例子之前,让我们来看看什么是for循环。
Python的for循环具有以下一般形式:
for var in sequence: body
循环体可以是任意Python语句序列。循环体的范围通过它在循环头(for var in sequence:部分)下面的缩进来表示。
关键字for后面的变量称为"循环索引”。它依次取sequence中的每个值,并针对每个值都执行一次循环体中的语句。通常,sequence部分由值"列表”构成。列表是Python中一个非常重要的概念,你将在后续节中了解更多。现在只要知道,可以在方括号中放置一系列表达式,从而创建一个简单的列表。下列交互示例有助于说明这一点:
for i in [0, 1, 2, 3]: print(i)0123for odd in [1, 3, 5, 7, 9]: print(odd * odd)19254981
你能看到这两个例子做了什么吗?依次使用列表中的每个值执行了循环体。列表的长度决定了循环执行的次数。在第一个例子中,列表包含4个值,即0至3,并且简单地打印了这些连续的i值。在第二个例子中,odd取前5个奇数的值,循环体打印了这些数字的平方。
现在,让我们回到这一节开始的例子(来自chaos.py)再看一下循环头:
for i in range(10):
将它与for循环的模板进行比较可以看出,最后一个部分range(10)必定是某种序列。事实上,range是一个内置的Python函数,用于"当场”生成一个数字序列。你可以认为range是一种数字序列的隐性描述。要明白range实际上做了什么,我们可以要求Python用另一个内置函数list,将range转换为一个简单的旧式列表:
list(range(10)) # turns range(10) into an explicit list[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
你看到这里发生了什么吗?表达式range(10)产生数字0到9的序列。使用range(10)的循环等价于使用那些数字的列表的循环。
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
一般来说,range(expr)将产生一个数字序列,从0开始,但不包括expr的值。如果你想一想,就会发现表达式的值确定了结果序列中的项数。在chaos.py中,我们甚至不关心循环索引变量使用了什么值(因为i没有在循环体中的任何位置引用)。我们只需要一个长度为10的序列,让循环体执行10次。
正如前面提到的,这种模式称为"计数循环”,它是使用确定循环的一种很常见的方式。如果你希望在程序中做一定次数的某些事,请用一个带有合适range的for循环。下面一个反复出现的Python编程习语,你需要记住:
for variable in range(expr):
表达式的值确定了循环执行的次数。索引变量的名称实际上并不重要,程序员经常使用i或j作为计数循环的循环索引变量。只要确保使用的标识符没有用于任何其他目的,否则你可能会不小心清除稍后需要的值。
循环的有趣和有用之处在于,它们改变程序"控制流”的方式。通常我们认为计算机是严格按顺序执行一系列指令。引入循环会导致Python退回去并重复执行一些语句。类似for循环的语句称为"控制结构”,因为它们控制程序其他部分的执行。
一些程序员发现,用图片的方式来思考控制结构是有帮助的,即所谓的"流程图”。流程图用一些框来表示程序的不同部分,并用框之间的箭头表示程序运行时的事件序列。图3用流程图描述了for循环的语义。
图3 for循环的流程图
如果你在理解for循环时遇到困难,可能会发现学习流程图很有用。流程图中的菱形框表示程序中的决定。当Python遇到循环头时,它检查序列中是否有项。如果答案为"是”,则循环索引变量被赋予序列中的下一项,然后执行循环体。一旦循环体完成,程序返回到循环头并检查序列中的下一个值。如果没有更多的项,循环就退出,程序移动到循环之后的语句。 示例程序:终值
我们用另一个编程过程的例子来结束本文。我们希望开发一个程序来确定投资的终值。我们将从对问题的分析开始。你知道存入银行账户的钱会赚取利息,这个利息随着时间的推移而累积。从现在起10年后,一个账户将有多少钱?显然,这取决于我们开始有多少钱(本金)以及账户赚多少利息。给定本金和利率,程序应该能够计算未来10年投资的终值。
我们继续制定程序的确切规格说明。记住,这是程序做什么的描述。输入应该是什么?我们需要用户输入初始投资金额,即本金。我们还需要说明账户赚多少利息。这取决于利率和计复利的频率。处理此问题的一种简单方法是让用户输入年度百分比率。无论实际利率和复利频率如何,年利率告诉我们一年内的投资收益。如果年利率为3%,那么100美元的投资将在一年的时间内增长到103美元。用户应如何表示年利率3%?有一些合理的选择。让我们假设用户提供一个小数,因此利率将输入为0.03。
这样就得到以下规格说明:
程序 终值输入 principal 投资于美元的金额。 APR 以十进制数表示的年度百分比利率。输出 投资10年后的终值。关系 一年后的价值由principal(1 + apr)给出。该公式需要应用10次。
接下来为程序设计一个算法。我们将使用伪代码,这样就可以阐明我们的想法而又不必担心Python的所有规则。对于我们的规格说明,算法看起来很简单。
打印介绍输入本金的金额(principal)输入年度百分比利率(apr)重复10次: principal = principal *(1 + apr)输出principal的值
如果你知道一些金融数学(或者只是一些基本代数)的知识,可能会意识到,在这个设计中并不一定要用循环。有一个公式可以利用乘幂一步算出终值。我在这里用了一个循环来展示另一个计数循环,另一个原因是这个版本适合进行一些修改,在本文末尾的编程练习中将讨论。无论如何,这个设计说明有时算法的计算方式可以让数学更容易。知道如何计算一年的利息,就让我们能计算未来任意年数的利息。
既然我们已经在伪代码中想明白了这个问题,现在该利用我们的Python新知识开发一个程序了。算法的每一行都转换为一条Python语句:
打印介绍(print语句,第2.4节)print(This program calculates the future value)print(of a 10-year investment.)输入本金的金额(数值input,第2.5.2节)principal = eval(input(Enter the initial principal:))输入年度百分比利率(数值input,第2.5.2节)apr = eval(input(Enter the annual interest rate:))重复10次:(计数循环,第2.6节)for i in range(10):计算principal = principal * (1 + apr)(简单赋值,第2.5.1节) principal = principal * (1 + apr)输出principal的值(print语句,第2.4节)print(The value in 10 years is:, principal)
该程序中的所有语句类型都已在本文中详细讨论过。如果有任何问题,请回头查看相关说明。特别要注意的是,计数循环模式用于应用10次利息公式。
就到这里了。下面是完成的程序:
# futval.py# A program to compute the value of an investment# carried 10 years into the futuredef main(): print(This program calculates the future value) print(of a 10-year investment.) principal = eval(input(Enter the initial principal:)) apr = eval(input(Enter the annual interest rate:)) for i in range(10): principal = principal * (1 + apr) print(The value in 10 years is:, principal)main()
注意,我添加了几个空行来分隔程序的输入、处理和输出部分。策略性地放置"空行”能让程序更具有可读性。
这就是我所举的例子,测试和调试是留给你的练习。 小结
本文介绍了开发程序的过程,以及实现简单程序所需的许多Python细节。下面是一些要点的快速小结。
编写程序需要一种系统的方法来解决问题,包括以下步骤。
1.问题分析:研究需要解决的问题。
2.程序规格说明:确定程序要做什么。
3.设计:用伪代码编写算法。
4.实现:将设计翻译成编程语言。
5.测试/调试:查找和修复程序中的错误。
6.维护:让程序保持最新,满足不断变化的需求。
许多简单的程序遵循输入、处理、输出(IPO)的模式。
程序由标识符和表达式构成的语句组成。
标识符是一些名称,它们以下划线或字母开头,后跟字母、数字或下划线字符的组合。Python中的标识符区分大小写。
表达式是产生数据的程序片段。表达式可以由以下部件组成:
字面量 字面量是特定值的表示。例如,3是数字3的字面量表示。
变量 变量是存储值的标识符。
运算符 运算符用于将表达式组合为更复杂的表达式。例如,在x + 3 * y中,使用了运算符+和*。
数字的Python运算符包括加法(+)、减法(-)、乘法(*)、除法(/)和乘幂(**)等常见的算术运算。
Python输出语句print将一系列表达式的值显示在屏幕上。
在Python中,使用等号(=)表示将值赋给变量。利用赋值,程序可以从键盘获得输入。Python还允许同时赋值,这对于利用单个提示获取多个输入值很有作用。
eval函数可用来对用户输入求值,但它是一种安全风险,不应该用于未知或不可信来源的输入。
确定循环是执行次数已知的循环。Python的for语句是一个循环遍历一系列值的确定循环。Python列表通常在for循环中用于为循环提供一系列值。
for语句的一个重要用途是实现计数循环,这是专门设计的循环,以便将程序的某些部分重复特定的次数。Python中的计数循环通过使用内置的range函数,来产生适当大小的数字序列。 判断对错
1.编写程序的最好方法是立即键入一些代码,然后调试它,直到它工作。
2.可以在不使用编程语言的情况下编写算法。
3.程序在写入和调试后不再需要修改。
4.Python标识符必须以字母或下划线开头。
5.关键词是好的变量名。
6.表达式由文字、变量和运算符构成。
7.在Python中,x = x + 1是一个合法的语句。
8.Python不允许使用单个语句输入多个值。
9.计数循环被设计为迭代特定次数。
10.在流程图中,菱形用于展示语句序列,矩形用于判断点。 多项选择
1.以下 项不是软件开发过程中的一个步骤。
a.规格说明 b.测试/调试 c.决定费用 d.维护
2.将摄氏度转换为华氏度的正确公式是 。
a. F = 9/5(C) + 32 b.F = 5/9(C) − 32
c. F = B2 − 4AC d.F = (212 – 32)/(100 – 0)
3.准确描述计算机程序将做什么来解决问题的过程称为 。
a.设计 b.实现 c.编程 d.规格说明
4.以下 项不是合法的标识符。
a.spam b.spAm c.2spam d.spam4U
5.下列 不在表达式中使用。
a.变量 b.语句 c.操作符 d.字面量
6.生成或计算新数据值的代码片段被称为 。
a.标识符 b.表达式 c.生成子句 d.赋值语句
7.以下 项不是IPO模式的一部分。
a.输入 b.程序 c.处理 d.输出
8.模板for lt;variablegt; in range(lt;exprgt;)描述了 。
a.一般for循环 b.赋值语句
c.流程图 d.计数循环
9.以下 项是最准确的Python赋值模型。
a.粘贴便签 b.变量盒子 c.同时 d.塑料尺
10.在Python中,获取用户输入通过一个特殊的表达式来实现,称为 。
a.for b.read c.同时赋值 d.input 讨论
1.列出并用你自己的语言描述软件开发过程中的六个步骤。
2.写出chaos.py程序(第1.6节),并识别程序的各部分如下:
圈出每个标识符。
为每个表达式加下划线。
在每一行的末尾添加注释,指示该行上的语句类型(输出、赋值、输入、循环等)。
3.解释确定循环、for循环和计数循环几个概念之间的关系。
4.显示以下片段的输出:
a.for i in range(5):
print(i * i)
b.for d in [3,1,4,1,5]:
print(d, end= )
c.for i in range(4):
print(Hello)
d.for i in range(5):
print(i, 2**i)
5.先写出一个算法的伪代码而不是立即投入Python代码,为什么是一个好主意?
6.除end之外,Python的print函数还支持其他关键字参数。其中一个关键字参数是sep。你认为sep参数是什么?(提示:sep是分隔符的缩写。通过交互式执行或通过查阅Python文档来检验你的想法)。
7.如果执行下面的代码,你认为会发生什么?
print(start)for i in range(0): print(Hello)print(end)
看看本文的for语句的流程图,帮助你弄明白。然后在程序中尝试这些代码,检验你的预测。 编程练习
1.一个用户友好的程序应该打印一个介绍,告诉用户程序做什么。修改convert.py程序(第2.2节),打印介绍。
2.在许多使用Python的系统上,可以通过简单地点击(或双击)程序文件的图标来运行程序。如果你能够以这种方式运行convert.py程序,你可能会发现另一个可用性问题。 程序在新窗口中开始运行,但程序一完成,窗口就会消失,因此你无法读取结果。在程序结束时添加一个输入语句,让它暂停,给用户一个读取结果的机会。下面这样的代码应该有效:
input(Press the Enter key to quit.)
3.修改avg2.py程序(第2.5.3节),找出三个考试成绩的平均值。
4.使用循环修改convert.py程序(第2.2节),让它在退出前执行5次。每次通过循环,程序应该从用户获得另一个温度,并打印转换的值。
5.修改convert.py程序(第2.2节),让它计算并打印一个摄氏温度和华氏度的对应表,从0℃到100℃,每隔10℃一个值。
6.修改futval.py程序(第2.7节),让投资的年数也由用户输入。确保更改最后的消息,以反映正确的年数。
7.假设你有一个投资计划,每年投资一定的固定金额。修改futval.py,计算你的投资的总累积值。该程序的输入将是每年投资的金额、利率和投资的年数。
8.作为APR的替代方案,账户所产生的利息通常通过名义利率和复利期数来描述。例如,如果利率为3%,利息按季度计算复利,则该账户实际上每3个月赚取0.75%的利息。请修改futval.py程序,用此方法输入利率。程序应提示用户每年的利率(rate)和利息每年复利的次数(periods)。要计算10年的价值,程序将循环10 * periods次,并在每次迭代中累积rate/period的利息。
9.编写一个程序,将温度从华氏温度转换为摄氏温度。
10.编写一个程序,将以千米为单位的距离转换为英里。1千米约为0.62英里。
11.编写一个程序以执行你自己选择的单位转换。确保程序打印介绍,解释它的作用。
12.编写一个交互式Python计算器程序。程序应该允许用户键入数学表达式,然后打印表达式的值。加入循环,以便用户可以执行许多计算(例如,最多100个)。注意:要提前退出,用户可以通过键入一个错误的表达式,或简单地关闭计算器程序运行的窗口,让程序崩溃。在后续图书节中,你将学习终止交互式程序的更好方法。
"异步图书”后台回复答案,得到本书的PPT和习题答案。
本文摘自《Python程序设计(第3版)》
Python之父作序推荐
Python编程入门经典
编辑推荐:
● 广泛使用计算机图形学——本书提供一个简单的图形软件包graphics.py作为示例。
● 生动有趣的例子——本书包含了完整的编程示例来解决实际问题。
● 亲切自然的行文——以自然的叙事风格介绍了重要的计算机科学概念。
● 灵活的螺旋式学习过程——简单地呈现概念,逐渐介绍新的思想,章节末加以巩固强化。
● 时机恰好地介绍对象——本书既不是严格的"早讲对象”,也不是"晚讲对象”,而是在命令式编程的基础上简要地介绍了对象概念。
● 提供丰富的教学素材——提供了大量的章末习题。还提供代码示例和教学PPT下载。
本书以Python语言为工具教授计算机程序设计。本书强调解决问题、设计和编程是计算机科学的核心技能。本书特色鲜明、示例生动有趣、内容易读易学,适合Python入门程序员阅读,也适合高校计算机专业的教师和学生参考。
作者简介
John Zelle是美国Wartburg大学数学和计算机系教授。他负责教授Python程序设计课程,并且结合多年的教学经验编写了本书,在美国高校受到普遍的欢迎。他还从事VR、AI等方面的研究,发表了一些机器学习方面的论文。
延伸推荐
小学生开始学Python,最接近AI的编程语言:安利一波Python书单 政策升温:大家都在学大数据,一大波好书推荐
一本基于Python语言的Selenium自动化测试书 8本新书,送出一本你喜欢的 AI经典书单| 入门人工智能该读哪些书?
点击关键词阅读更多新书:
Python|机器学习|Kotlin|Java|移动开发|机器人|有奖活动|Web前端|书单
在"异步图书”后台回复"关注”,即可免费获得2000门在线视频课程;推荐朋友关注根据提示获取赠书链接,免费得异步图书一本。赶紧来参加哦!
扫一扫上方二维码,回复"关注”参与活动!
今日活动
转发本文到朋友圈,截图给"异步图书后台”,并在文末留言说出你对本文的感想,1.3日我们将选出1名读者赠送本书。
昨日获奖读者:想当年 自在
请获奖读者,在表单中填写获奖信息https://www.wenjuan.in/s/m2iaqif/
点击阅读原文,购买《Python程序设计(第3版)》一书返回搜狐,查看更多
责任编辑: