View Categories

Python 教程 2 — 变量、表达式和语句

3 min read

编程语言最强大的特性之一,是操作变量的能力。变量是指向某个值的名称。

1.赋值语句 #

赋值语句(assignment statement)会新建变量,并为这个变量赋值。

>>> message = 'And now for something completely different'
>>> n = 17
>>> pi = 3.141592653589793

这个例子进行了三次赋值。 第一次将一个字符串赋给一个叫message的新变量; 第二次将整型数17赋给n; 第三次将ππ的(近似)值赋给pi。

在纸上表示变量的一个常见方法,是写下变量名,并用箭头指向变量的值。 这种图被称为状态图(state diagram),因为它展示了每个变量所处的状态(可以把其看成是变量的心理状态)。 图2-1展示了前面例子的结果。

图2-1:状态图。

2.变量名 #

程序员通常为变量选择有意义的名字—它们可以记录该变量的用途。

变量名可以任意长。它们可以包括字母和数字,但是不能以数字开头。 使用大写字母是合法的,但是根据惯例,变量名只使用小写字母。

下划线_可以出现在变量名中。 它经常用于有多个单词的变量名,例如my_name或者airspeed_of_unladen_swallow

如果你给了变量一个非法的名称,解释器将抛出一个语法错误:

>>> 76trombones = 'big parade'
SyntaxError: invalid syntax
>>> more@ = 1000000
SyntaxError: invalid syntax
>>> class = 'Advanced Theoretical Zymurgy'
SyntaxError: invalid syntax

76trombones是非法的,因为它以数字开头。more@是非法的,因为它包含了一个非法字符@。 但是,class错在哪儿了呢?

原来,class是Python的关键字(keywords)之一。 解释器使用关键字识别程序的结构,它们不能被用作变量名。

Python 3有以下关键词:

Falseclassfinallyisreturn
Nonecontinueforlambdatry
Truedeffromnonlocalwhile
anddelglobalnotwith
aselififoryield
assertelseimportpass
breakexceptinraise

你没有必要背诵上面的关键词。大部分的开发环境会用不同的颜色区别显示关键词;如果你不小心使用关键词作为变量名,你肯定会发现的。

3.表达式和语句 #

表达式(expression)是值、变量和运算符的组合。 值自身也被认为是一个表达式,变量也是,因此下面都是合法的表达式:

>>> 42
42
>>> n
17
>>> n + 25
42

当你在提示符后输入表达式时,解释器会 ** 计算(evaluate)**该表达式,这就意味着解释器会求它的值。在上面的例子中,n的值是17,n + 25的值是42。

语句(statement)是一个会产生影响的代码单元,例如新建一个变量或显示某个值。

>>> n = 17
>>> print(n)

第一行是一个赋值语句,将某个值赋给了n。第二行是一个打印语句,在屏幕上显示n的值。

当你输入一个语句后,解释器会执行(execute)这个语句,即按照语句的指令完成操作。一般来说,语句是没有值的。

4.脚本模式 #

到目前为止,我们都是在交互模式(interactive mode)下运行Python,即直接与解释器进行交互。交互模式对学习入门很有帮助,但是如果你需要编写很多行代码,使用交互模式就不太方便了。

另一种方法是将代码保存到一个被称为脚本(script)的文件里,然后以脚本模式(script mode)运行解释器并执行脚本。按照惯例,Python脚本文件名的后缀是.py。

由于Python支持这两种模式,在将代码写入脚本之前,你可以在交互模式下对代码片段进行测试。不过,交互模式和脚本模式之间存在一些差异,可能会让你感到疑惑。

举个例子,如果你把Python当计算器使用,你可能会输入下面这样的代码:

>>> miles = 26.2
>>> miles * 1.61
42.182

第一行将一个值赋给miles,但是并没有产生可见的效果。 第二行是一个表达式,因此解释器计算它并将结果显示出来。 结果告诉我们,一段马拉松大概是42公里。

但是如果你将相同的代码键入一个脚本并且运行它,你得不到任何输出。 在脚本模式下,表达式自身不会产生可见的效果。虽然Python实际上计算了表达式,但是如果你不告诉它要显示结果,它是不会那么做的。

miles = 26.2
print(miles * 1.61)

这个行为开始可能有些令人费解。

一个脚本通常包括一系列语句。 如果有多于一条的语句,那么随着语句逐个执行,解释器会逐一显示计算结果。

例如,以下脚本

print(1)
x = 2
print(x)

产生的输出结果是

1
2

赋值语句不产生输出。

在Python解释器中键入以下的语句,看看他们的结果是否符合你的理解:

5
x = 5
x + 1

现在将同样的语句写入一个脚本中并执行它。输出结果是什么? 修改脚本,将每个表达式变成打印语句,再次运行它。

5.运算顺序 #

当一个表达式中有多于一个运算符时,计算的顺序由运算顺序(order of operations)决定。 对于算数运算符,Python遵循数学里的惯例。 缩写PEMDAS有助于帮助大家记住这些规则:

括号(Parentheses)具有最高的优先级,并且可以强制表达式按你希望的顺序计算。 因为在括号中的表达式首先被计算,那么2 * (3-1)的结果是4,(1+1)**(5-2)的结果是8。 你也可以用括号提高表达式的可读性,如写成(minute * 100) / 60,即使这样并不改变运算的结果。

指数运算(Exponentiation)具有次高的优先级,因此1 + 2**3的结果是9而非27, 2 * 3**2的结果是18而非36。

乘法(Multiplication)和除法(Division)有相同的优先级, 比加法(Addition)和减法(Subtraction)高,加法和减法也具有相同的优先级。 因此2*3-1是5而非4,6+4/2是8而非5。

具有相同优先级的运算符按照从左到右的顺序进行计算(除了指数运算)。 因此表达式degrees / 2 * pi中,除法先运算,然后结果被乘以pi。 为了被2π2π除,你可以使用括号,或者写成degrees / 2 / pi。

简单地来讲就是:括号>指数运算>乘法=除法>加法=减法

我不会费力去记住这些运算符的优先级规则。如果看完表达式后分不出优先级,我会使用括号使计算顺序变得更明显。

6.字符串运算 #

一般来讲,你不能对字符串执行数学运算,即使字符串看起来很像数字, 因此下面这些表达式是非法的:

'2'-'1'    'eggs'/'easy'    'third'*'a charm'

但有两个例外,+ 和 *。

加号运算符 + 可用于 字符串拼接(string concatenation),也就是将字符串首尾相连起来。例如:

>>> first = 'throat'
>>> second = 'warbler'
>>> first + second
throatwarbler

乘法运算符* 也可应用于字符串;它执行重复运算。 例如,'Spam'*3的结果是'SpamSpamSpam'。 如果其中一个运算数是字符串,则另外一个必须是整型数。

+和*的这个用法,类比加法和乘法也讲得通。 就像4*3与4+4+4等价一样, 我们也会期望'Spam'*3'Spam'+'Spam'+'Spam'等价,而事实上的确如此。 另一方面,字符串拼接和重复与整数的加法和乘法也有很大的不同。 你能想出来一个加法具有而字符串拼接不具有的特性么?

7.注释 #

随着程序变得越来越大,越来越复杂,它们的可读性也越来越差。 形式语言是稠密的,通常很难在读一段代码后,说出其做什么或者为什么这样做。

因此,在你的程序中用自然语言做笔记,解释程序做什么通常是比较好的办法。 这些标注被称为注释(comments),以#符号开始。

# 计算逝去的时间占一小时的比例
percentage = (minute * 100) / 60

此例中,注释独立一行。你也可以将注释放在行尾:

percentage = (minute * 100) / 60     # 逝去时间占一小时的比例

从#开始到行尾的所有内容都会被解释器忽略—其对程序执行没有影响。

在注释中记录代码不明显的特征,是最有帮助的。 假设读者能够读懂代码做了什么是合理的; 但是解释代码为什么这么做则更有用。

下面这个注释只是重复了代码,没有什么用:

v = 5     # 将5赋值给v

下面的注释包括了代码中没有的有用信息:

v = 5     # 加速度,单位:米/秒

好的变量名能够减少对注释的需求,但是长变量名使得表达式很难读, 因此这里有个平衡问题。

8.调试 #

程序中可能会出现下面三种错误:语法错误(syntax error)、运行时错误(runtime error)和语义错误(semantic error)。我们如果能够分辨出三者区别,有助于快速追踪这些错误。语法错误:

语法指的是程序的结构及其背后的规则。例如,括号必须要成对出现,所以(1 + 2)是合法的,但是8)则是一个 语法错误

如果你的程序中存在一个语法错误,Python会显示一条错误信息,然后退出运行。你无法顺利运行程序。在你编程生涯的头几周里,你可能会花大量时间追踪语法错误。随着你的经验不断积累,犯的语法错误会越来越少,发现错误的速度也会更快。运行时错误:

第二种错误类型是运行时错误,这么称呼是因为这类错误只有在程序开始运行后才会出现。这类错误也被称为 异常(exception),因为它们的出现通常说明发生了某些特别的(而且不好的)事情。

在前几章提供的简单程序中,你很少会碰到运行时错误,所以你可能需要一段时间才会接触到这种错误。语义错误:

第三类错误是“语义”错误,即与程序的意思的有关。如果你的程序中有语义错误,程序在运行时不会产生错误信息,但是不会返回正确的结果。它会返回另外的结果。严格来说,它是按照你的指令在运行。

识别语义错误可能是棘手的,因为这需要你反过来思考,通过观察程序的输出来搞清楚它在做什么。

9.练习题 #

习题 2-1 #

和上一章一样,我还是要建议大家在学习新特性之后,在交互模式下充分试验,故意犯一些错误,看看到底会出什么问题。

  • 我们已经知道 n = 42 是合法的。那么 42 = n 呢?
  • x = y = 1 又合法吗?
  • 在某些编程语言中,每个语句都是以分号  结束的。如果你在一个Python语句后也以分号结尾,会发生什么?
  • 如果在语句最后带上句号呢?
  • 在数学记法中,你可以将 xx 和 yy 像这样相乘:xyxy。如果你在Python中也这么写的话,会发生什么?

习题 2-2 #

继续练习将Python解释器当做计算器使用:

  1. 半径为rr的球体积是43πr343πr3。 半径为5的球体积是多少?
  2. 假设一本书的零售价是$24.95,但书店有40%的折扣。运费则是第一本$3,以后每本75美分。 购买60本的总价是多少?
  3. 如果我上午6:52离开家, 以放松跑(easy pace)的速度跑1英里(每英里8:15,即每英里耗时8分15秒),再以 节奏跑(tempo)的速度跑3英里(每英里7:12,即每英里耗时7分12秒),之后又以放松跑的速度跑1英里,我什么时候回到家吃早饭?

贡献者 #

  1. 翻译:@bingjin
  2. 校对:@bingjin
  3. 参考:@carfly

推荐阅读 #

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。


​Python实用宝典 (pythondict.com)
关注公众号:Python实用宝典
更多精彩文章等你阅读

Powered by BetterDocs

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

退出移动版
微信支付
请使用 微信 扫码支付