2-2-if-测试和语法规则
1. if 语句
1.1 通用格式
if,后面跟一个或多个可选的 elif(“else if”),以及一个最终可选的 else 块。
一般形式如下:
if <test1>:
<statements1>
elif <test2>:
<statements2>
else:
<statements3>
1.2 基本例子
if 1:
print('true')
true
1.3 多路分支
x = 'killer rabbit'
if x == 'roger':
print("how's jessica?")
elif x == 'bugs':
print("what's up doc?")
else:
print('Run away! Run away!')
Run away! Run away!
elif 和 else 部分都可以省略,而且每一段中可以嵌套一个以上的语句。
Python 中没有 switch 或 case 语句,多路分支是写成一系列的 if/elif 测试,或者对字典进行索引运算或搜索列表。
因为字典和列表可在运行时创建,有时会比硬编码的 if 逻辑更有灵活性
choice = 'ham'
print({'spam': 1.25, # 基于字典的 'switch'
'ham': 1.99, # 默认使用 get
'eggs': 0.99,
'bacon': 1.10}[choice])
1.99
这个字典是多路分支:根据键的选择进行索引,再分支到一组值的其中一个,很像 C 语言的 switch。
字典默认值能编码到 get 方法调用或异常捕捉中,在字典式的多路分支中也可用这些技术编写默认动作:
branch = {'spam': 1.25,
'ham': 1.99,
'eggs': 0.99}
print(branch.get('spam', 'Bad choice'))
1.25
print(branch.get('bacon', 'Bad choice'))
Bad choice
位于一条 if 语句中的 in 成员测试也有同样的效果:
choice = 'bacon'
if choice in branch:
print(branch[choice])
else:
print('Bad choice')
Bad choice
try 语句是一种通过捕获和处理异常来处理默认值的通用方法:
try:
print(branch[choice])
except KeyError:
print('Bad choice')
Bad choice
虽然字典式多路分支在处理动态数据的程序中很有用,但编写 if 语句是执行多路分支最直接的方式。
编写代码时的原则是:有疑虑的时候,就遵循简易性原则和可读性原则。
2. Python 语法规则
- 语句是逐个运行的,除非你不这样编写。
- 块和语句的边界会自动检测。
- 复合语句=首行+“:”+缩进语句。
- 空白行、空格以及注释通常都会忽略。
- 文档字符串(docstring)会忽略,但会保存并由工具显示。
2.1 代码块分隔符
Python 会自动以行缩进检测块的边界,缩进至右侧相同距离的所有语句属于同一块的代码。换句话说,块内的语句会垂直对齐,就好像在一栏之内。块会在文件末尾或者碰到缩进量较少的行时结束,而更深层的嵌套块就是比所在块的语句进一步向右缩进。
x = 1
if x:
y = 2
if y:
print('block2')
print('block1')
print('block0')
通常来说,顶层(无嵌套)代码必须位于第一栏开始,嵌套块可以从任何栏开始,缩进可以由任意的空格和制表符组成,只要特定的单个块中的所有语句都相同即可。
避免混合使用制表符和空格。
2.2 语句的分隔符
Python 的语句一般都是在其所在行的末尾结束的,不过,当语句太长、难以单放在一行时,有些特殊的规则可使其位于多行之中。
- **如果使用语法括号对,语句就可以横跨数行。**如果在封闭的()、{}或[]这类配对中编写代码,Python就可以让你在下一行继续输入语句。
- **如果语句以反斜线结尾,就可以横跨数行。**这是有点过时的功能,但是如果语句需要横跨数行,也可以在前一行的末尾加上反斜线(\),以表示要在下一行继续输入。因为可以在较长结构两侧加上括号以便继续输入,反斜线几乎都已经不再使用。这种方法容易导致错误:偶尔忘掉一个 \ 通常会产生语法错误。
- **字符串常量有特殊规则。**三重引号字符串块可以横跨数行。相邻字符串常量是隐式地连接起来的。
- **其他规则。**可以用分号终止语句:这种惯例有时用于把一个以上的简单(非复合)语句挤进单个的行中。注释和空白行能出现在文件的任意之处。注释(以#字符开头)则在其出现的行的末尾终止。
2.3 一些特殊情况
L = ['Good',
'Bad',
'Ugly'] # 括号可以横跨数行
括号可以存放表达式、函数参数、函数的首行、元组和生成器表达式,以及可以放到花括号中的任何内容。
如果程序代码需要横跨数行,通常可以改用开放对技术——直接把语句的部分包含在圆括号中:
if (a == b and c == d and
d == e and e == f):
print('new')
Python 允许在相同行上编写一个以上的非复合语句,由分号隔开:
x = 1; y = 2; print(x)
如果两个字符串常量彼此相邻地出现,它们会合并,就好像它们之间已经放置了一个 + ——当和开放对规则一起使用时,包括在圆括号中就允许这种形式跨越多行。
S = """
aaa
bbb
ccc"""
print(S)
aaa
bbb
ccc
S = ('aaa'
'bbb' # 注释将被忽略
'ccc')
print(S)
aaabbbccc
上面第一个示例在换行处插入换行字符,并且把 '\naaa\nbbb\nccc'
赋给S,而第二个示例隐式地合并,并且把 S 赋值为 aaabbbccc
。
Python 可把复合语句的主体上移到首行,只要该主体只是简单语句:
if 1: print('hello')
hello
3. 真值和布尔值测试
Python 的布尔运算符和 C 这类语言的布尔运算符有些不同,在 Python 中:
- 所有对象本质上不是真就是假。
- 任何非零数字或非空对象都为真。
- 数字零、空对象以及特殊对象 None 都被认作是假。
- 比较和相等测试会递归地应用在数据结构中。
- 比较和相等测试会返回 True 或 False(1 和 0 的特殊版本)。
- 布尔 and 和 or 运算符会返回真或假的操作对象。
- 一旦求出结果,布尔运算符就停止计算(“短路”)
布尔运算符是用于结合其他测试的结果,Python 中有三种布尔表达式运算符:
- X and Y
- X or Y
- not X
此处,X 和 Y 可以是任何真值或者返回真值的表达式(例如,相等测试、范围比较等)。
Python 中值的比较会返回 True 或 False 作为其真值结果。
2 < 3, 3 < 2 # 小于:返回 True 或 False
(True, False)
and 和 or 运算符总会返回对象,不是运算符左侧的对象,就是右侧的对象。
就 or 测试而言,Python 会由左至右求算操作对象,然后返回第一个为真的操作对象,Python 会在其找到的第一个真值操作数的地方停止,因为求出结果后,就会使表达式其余部分短路(终止):
2 or 3, 3 or 2 # 如果真就返回左侧操作数,否则返回右侧操作数(右侧操作数可能是真或假)
(2, 3)
[] or 3
3
[] or {}
{}
在求出结果时,and 运算也会立刻停止。就此而言,Python 由左至右计算操作数,并且停在第一个为假的对象上,因为它决定了结果——false and 任意对象的结果总是 false:
2 and 3, 3 and 2
(3, 2)
[] and {}
[]
3 and []
[]
4. if/else 三元表达式
if X:
A = Y
else:
A = Z
有时这类语句中涉及的元素相当简单,用四行代码编写似乎太浪费了。Python 2.5 引入了新的表达式格式,让我们可以在一个表达式中编写出相同的结果:
A = Y if X else Z
只有当 X 为真,Python 才会执行表达式 Y,只有当 X 为假,才会执行表达式 Z。这就是短路运算,就像布尔运算符一样的行为。
A = 't' if 'spam' else 'f' # 非空即为真
A
't'
A = 't' if '' else 'f'
A
'f'