Think Python/变量、表达式和语句
值和类型
[edit | edit source]值是程序操作的基本事物之一,例如字母或数字。我们到目前为止见过的值包括1, 2,以及 'Hello, World!'
。
这些值属于不同的类型2是一个整数,而 'Hello, World!'
是一个字符串,之所以称为字符串,是因为它包含一个字母“字符串”。您可以(以及解释器)通过它们是否包含在引号中来识别字符串。
print 语句也适用于整数。
>>> print (4)
4
如果您不确定某个值的类型,解释器可以告诉您。
>>> type('Hello, World!')
<type 'str'>
>>> type(17)
<type 'int'>
不出所料,字符串属于类型str,而整数属于类型int。不太明显的是,带小数点的数字属于一种称为float的类型,因为这些数字以一种称为浮点数的格式表示。
>>> type(3.2)
<type 'float'>
那么像 '17'
和 '3.2'
这样的值呢?它们看起来像数字,但它们包含在像字符串一样的引号中。
>>> type('17')
<type 'str'>
>>> type('3.2')
<type 'str'>
它们是字符串。
当您输入一个大整数时,您可能会倾向于在三位数的组之间使用逗号,例如1,000,000。这在 Python 中不是一个合法的整数,但它是合法的
>>> print 1,000,000
1 0 0
嗯,这完全不是我们预期的!Python 将1,000,000解释为一个以逗号分隔的整数序列,它以空格分隔的形式打印出来。
这是我们见过的第一个语义错误示例:代码在没有产生错误消息的情况下运行,但它并没有做“正确”的事情。
变量
[edit | edit source]编程语言最强大的功能之一是能够操作变量。变量是引用值的名称。
赋值语句创建新的变量并赋予它们值
>>> message = 'And now for something completely different'
>>> n = 17
>>> pi = 3.1415926535897931
此示例进行了三个赋值。第一个将字符串赋值给一个名为message的新变量;第二个将整数17赋值给n;第三个将 π 的(近似)值赋值给pi.
。在纸上表示变量的一种常见方法是写下名称,并用箭头指向变量的值。这种图被称为状态图,因为它显示了每个变量的状态(将其视为变量的心态)。此图显示了上一个示例的结果
message
|
'And now for something completely different'
| |
n
|
17
| |
pi
|
3.1415926535897931
|
要显示变量的值,可以使用 print 语句
>>> print n
17
>>> print pi
3.14159265359
变量的类型是它引用的值的类型。
>>> type(message)
<type 'str'>
>>> type(n)
<type 'int'>
>>> type(pi)
<type 'float'>
练习 1
[edit | edit source]如果您输入一个以零开头的整数,您可能会得到一个令人困惑的错误
>>> zipcode = 02492
^
SyntaxError: invalid token
其他数字似乎可以工作,但结果很奇怪
>>> zipcode = 02132
>>> print zipcode
1114
你能弄清楚发生了什么事吗?提示:打印值 01
、010
、0100
和 01000
。
变量名和关键字
[edit | edit source]程序员通常会选择对变量有意义的名称——它们记录了变量的使用目的。
变量名可以任意长。它们可以包含字母和数字,但必须以字母开头。使用大写字母是合法的,但最好以小写字母开头变量名(您将在后面看到原因)。
下划线字符 (_
) 可以出现在名称中。它通常用于包含多个单词的名称,例如 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 的关键字之一。解释器使用关键字来识别程序的结构,它们不能用作变量名。
Python 有 31 个关键字
以及
|
del
|
from
|
not
|
while
|
as
|
elif
|
global
|
or
|
with
|
assert
|
else
|
if
|
pass
|
yield
|
break
|
except
|
import
|
print
| |
class
|
exec
|
in
|
raise
| |
continue
|
finally
|
is
|
return
| |
def
|
for
|
lambda
|
try
|
您可能需要将此列表随时备用。如果解释器抱怨您的变量名称之一,而您不知道原因,请查看它是否在此列表中。
如果您在了解 Python 的文本编辑器中编写代码,您可能会发现它可以轻松地让您发现此类关键字冲突,因为它以与普通变量不同的颜色显示关键字。此功能称为语法高亮,大多数程序员都认为它是必不可少的。本书为其示例代码使用语法高亮,因此在以下示例中
ok_variable = 42
yield = 42
您可以看到 yield
被识别为关键字,而不是普通变量,因为它被涂成绿色。
语句
[edit | edit source]语句是 Python 解释器可以执行的代码单元。我们已经看到了两种语句:print 和赋值。
当您在交互模式下键入语句时,解释器会执行它并显示结果(如果有)。
脚本通常包含一系列语句。如果有多个语句,则结果将随着语句执行而逐一出现。
例如,脚本
print 1
x = 2
print x
产生以下输出
1
2
赋值语句不会产生输出。
运算符和操作数
[edit | edit source]运算符是代表计算(如加法和乘法)的特殊符号。运算符应用到的值称为操作数。
运算符+, -, *, /以及**执行加法、减法、乘法、除法和求幂,如以下示例所示
20+32 hour-1 hour*60+minute minute/60 5**2 (5+9)*(15-7)
在其他一些语言中,^
用于求幂,但在 Python 中,它是一个称为异或的按位运算符。我不会在本手册中介绍按位运算符,但您可以在以下地址阅读相关内容:wiki.python.org/moin/BitwiseOperators.
除法运算符可能不会按预期执行
>>> minute = 59
>>> minute/60
0
的值minute是 59,在传统的算术运算中,59 除以 60 等于 0.98333,而不是 0。造成这种差异的原因是 Python 执行的是向下取整除法。[1]
当两个操作数都是整数时,结果也是整数;向下取整除法会将小数部分截断,因此在本例中,它向下取整为零。
如果操作数之一是浮点数,Python 将执行浮点数除法,结果为一个float:
>>> minute/60.0
0.98333333333333328
表达式
[edit | edit source]一个表达式是值、变量和运算符的组合。一个值本身被认为是一个表达式,变量也是,因此以下都是合法表达式(假设变量x已经被赋值了)
17
x
x + 17
如果你在交互模式下输入一个表达式,解释器会计算它并显示结果
>>> 1 + 1
2
但在脚本中,一个表达式本身不会做任何事情!这是初学者常犯的错误。
练习 2
[edit | edit source]在 Python 解释器中输入以下语句,看看它们做了什么
5
x = 5
x + 1
现在将相同的语句放到脚本中并运行它。输出是什么?通过将每个表达式转换为 print 语句来修改脚本,然后再次运行它。
运算顺序
[edit | edit source]当一个表达式中出现多个运算符时,运算顺序取决于优先级规则。对于数学运算符,Python 遵循数学惯例。首字母缩略词PEMDAS是记忆规则的一种有用方法
- Parentheses 具有最高优先级,可用于强制表达式按您想要的顺序计算。由于括号内的表达式首先计算,因此2 * (3-1)为 4,而(1+1)**(5-2)为 8。您也可以使用括号使表达式更易于阅读,例如(minute * 100) / 60,即使它不改变结果。
- Exponentiation 具有次高优先级,因此2**1+1为 3,而不是 4,并且3*1**3为 3,而不是 27。
- Multiplication 和 Division 具有相同的优先级,高于 Addition 和 Subtraction,它们也具有相同的优先级。所以2*3-1为 5,而不是 4,并且6+4/2为 8,而不是 5。
- 具有相同优先级的运算符从左到右计算。因此在表达式degrees / 2 * pi中,除法首先发生,结果乘以pi。要除以 2 π,您可以重新排序操作数或使用括号。
字符串操作
[edit | edit source]一般来说,您不能对字符串执行数学运算,即使字符串看起来像数字,因此以下操作是非法的
'2'-'1' 'eggs'/'easy' 'third'*'a charm'
the+运算符与字符串一起使用,但它可能不会按预期执行:它执行串联,这意味着将字符串首尾相连。例如
first = 'throat'
second = 'warbler'
print first + second
该程序的输出是throatwarbler.
the*运算符也适用于字符串;它执行重复。例如,’Spam’*3是 'SpamSpamSpam'
。如果操作数之一是字符串,另一个必须是整数。
这种使用+以及*有意义,因为它与加法和乘法类似。就像4*3等同于4+4+4一样,我们希望 'Spam'*3
与 'Spam'+'Spam'+'Spam'
相同,它确实相同。另一方面,字符串串联和重复与整数加法和乘法有一个显著的区别。你能想到加法具有的而字符串串联不具有的属性吗?
注释
[edit | edit source]随着程序变得越来越大、越来越复杂,它们也越来越难读。形式语言很密集,通常很难查看一段代码并弄清楚它在做什么,或者为什么。
因此,最好在程序中添加注释,以用自然语言解释程序在做什么。这些注释称为注释,它们以#
符号开头
# compute the percentage of the hour that has elapsed
percentage = (minute * 100) / 60
在这种情况下,注释出现在一行中。您也可以将注释放在一行的末尾
percentage = (minute * 100) / 60 # percentage of an hour
从#
到行尾的所有内容都会被忽略——它不会对程序产生任何影响。
注释在记录代码的非明显特征时最有用。可以合理地假设读者可以弄清楚代码做什么;解释为什么更有用。
此注释与代码冗余且无用
v = 5 # assign 5 to v
此注释包含代码中没有的有用信息
v = 5 # velocity in meters/second.
好的变量名可以减少对注释的需要,但过长的名称会使复杂的表达式难以阅读,因此存在权衡。
调试
[edit | edit source]此时,您最有可能遇到的语法错误是无效的变量名,例如class以及yield,它们是关键字,或者 odd~job
和 US$
,它们包含无效字符。
如果您在变量名中放一个空格,Python 会认为它是两个没有运算符的操作数
>>> bad name = 5
SyntaxError: invalid syntax
对于语法错误,错误消息并没有多大帮助。最常见的错误消息是SyntaxError: invalid syntax以及SyntaxError: invalid token,它们都不太具有信息量。
您最有可能遇到的运行时错误是“使用前定义”;也就是说,在为变量赋值之前尝试使用它。如果拼错了变量名,就会发生这种情况
>>> principal = 327.68
>>> interest = principle * rate
NameError: name 'principle' is not defined
变量名区分大小写,因此LaTeX与latex.
不同
>>> 1.0 / 2.0 * pi
此时,语义错误最有可能的原因是运算顺序。例如,要计算 1/2 π,您可能会尝试编写
但除法首先发生,因此您将得到 π / 2,它与 1/2 π 不一样!Python 无法知道您想要写什么,因此在这种情况下您不会收到错误消息;您只会得到错误的答案。
词汇表- [edit | edit source]
- 值
- 数据的基本单元之一,例如数字或字符串,程序对其进行操作。
- 类型int值的类别。到目前为止,我们看到的类型是整数(类型float),浮点数(类型str).
- ),和字符串(类型
- 整数
- 表示整数的类型。
- 浮点数
- 表示带小数部分的数字的类型。
- 字符串
- 表示字符序列的类型。
- 变量
- 指代值的名称。
- 语句
- 代表命令或操作的代码部分。到目前为止,我们看到的语句是赋值和 print 语句。
- 赋值
- 将值赋给变量的语句。
- 状态图
- 一组变量及其所指值的图形表示。
- 关键字if, def编译器用来解析程序的保留字;您不能使用诸如while和
- 之类的关键字作为变量名。
- 运算符
- 表示简单计算的特殊符号,例如加法、乘法或字符串串联。
- 操作数
- 运算符作用的值之一。
- 向下取整除法
- 将两个数字相除并砍掉小数部分的操作。
- 表达式
- 表示单个结果值的变量、运算符和值的组合。
- 计算
- 通过按顺序执行运算来简化表达式以生成单个值。
- 优先级规则
- 控制包含多个运算符和操作数的表达式计算顺序的规则集。
- 串联
- 将两个操作数首尾相连。
- 注释
程序中的信息,意在供其他程序员(或阅读源代码的任何人)使用,对程序执行没有影响。
练习[edit | edit source]
练习 3[edit | edit source]
width = 17
height = 12.0
delimiter = '.'
假设我们执行以下赋值语句
width/2
width/2.0
height/3
1 + 2 * 5
delimiter * 5
对于以下每个表达式,写出表达式的值和类型(表达式的值的类型)。
使用 Python 解释器检查您的答案。
练习 4[edit | edit source]
- 半径为 的球体的体积为 4/3 π 。半径为 5 的球体的体积是多少?提示:392.6 是错误的!
- 假设一本图书的定价为 24.95 美元,但书店可以享受 40% 的折扣。第一本图书的运费为 3 美元,每增加一本图书运费为 75 美分。60 本图书的批发价是多少?
- 如果我早上 6:52 离开家,以轻松的速度(每英里 8:15)跑 1 英里,然后以中速(每英里 7:12)跑 3 英里,最后再以轻松的速度跑 1 英里,我几点回到家吃早餐?
- ↑ 在 Python 3.0 中,此除法的结果为 float。新运算符 // 执行整数除法。