4.2 选择结构
常见的选择结构有单分支选择结构、双分支选择结构、多分支选择结构以及嵌套的分支结构,也可以构造跳转表来实现类似的逻辑。另外,循环结构和异常处理结构中也可以带有else子句,可以看作是特殊形式的选择结构,请参考4.3节和11.1节的介绍。
4.2.1 单分支选择结构
单分支选择结构语法如下所示,其中表达式后面的冒号“:”是不可缺少的,表示一个语句块的开始,并且语句块必须做相应地缩进,一般是以4个空格为缩进单位。
if表达式: 语句块
当表达式值为True或其他与True等价的值时,表示条件满足,语句块被执行,否则该语句块不被执行,而是继续执行后面的代码(如果有的话),如图4-2所示。
图4-2 单分支选择结构
下面的代码演示了单分支选择结构的用法:
x=input('Input two numbers:') a, b=map(int, x.split()) if a>b: a, b=b, a #序列解包,交换两个变量的值 print(a, b)
在Python中,代码的缩进非常重要,缩进是体现代码逻辑关系的重要方式,同一个代码块必须保证相同的缩进量。在实际开发中,只要遵循一定的约定,Python代码的排版是可以降低要求的,例如下面的代码,虽然不建议这样写,但确实是可以执行的。
>>>if 3>2: print('ok') #如果语句较短,可以直接写在分支语句后面 ok >>>if True:print(3); print(5) #在一行写多个语句,使用分号分隔 3 5
4.2.2 双分支选择结构
双分支选择结构的语法为
if表达式: 语句块1 else: 语句块2
当表达式值为True或其他等价值时,执行语句块1,否则执行语句块2。语句块1或语句块2总有一个会执行,然后再执行后面的代码(如果有的话),如图4-3所示。
图4-3 双分支选择结构
下面的代码通过鸡兔同笼问题演示了双分支结构的用法。
jitu, tui=map(int, input(’请输入鸡兔总数和腿总数:').split()) tu=(tui-jitu*2)/2 if int(tu)==tu: print(’鸡:{0},兔:{1}'.format(int(jitu-tu), int(tu))) else: print(’数据不正确,无解’)
另外,Python还提供了一个三元运算符,并且在三元运算符构成的表达式中还可以嵌套三元运算符,可以实现与选择结构相似的效果。语法为
value1 if condition else value2
当条件表达式condition的值与True等价时,表达式的值为value1,否则表达式的值为value2。另外,value1和value2本身也可以是复杂表达式,也可以包含函数调用,甚至可以是三元运算符构成的表达式。这个结构的表达式也具有惰性求值的特点。
>>>a=5 >>>print(6) if a>3 else print(5) 6 >>>print(6 if a>3 else 5) #虽然结果与上一行代码一样,但代码含义不同 6 >>>b=6 if a>13 else 9 #赋值运算符的优先级非常低 >>>b 9 >>>x=math.sqrt(9) if 5>3 else random.randint(1,100) #还没有导入math模块 NameError: name'math'is not defined >>>import math >>>x=math.sqrt(9) if 5>3 else random.randint(1,100) #还没有导入random模块 #但表达式5>3的值为True #所以可以正常运行 >>>x=math.sqrt(9) if 2>3 else random.randint(1,100) #条件表达式2>3的值为False #需要计算第二个表达式 #但此时还没导入random #所以出错 NameError: name'random'is not defined >>>import random #导入random,成功执行 >>>x=math.sqrt(9) if 2>3 else random.randint(1,100)
虽然三元运算符可以嵌套使用,可以实现复杂的多分支选择结构的效果,但这样的代码可读性非常差,不建议使用。
>>>x=3 >>>(1 if x>2 else 0) if f(x)>5 else ('a'if x<5 else'b') #可以嵌套使用,建议不这样写 1 >>>x=0 >>>(1 if x>2 else 0) if f(x)>5 else ('a'if x<5 else'b') 'a'
4.2.3 多分支选择结构
多分支选择结构的语法为
if表达式1: 语句块1 elif表达式2: 语句块2 elif表达式3: 语句块3 else: 语句块n
其中,关键字elif是else if的缩写。下面的代码演示了如何利用多分支选择结构将成绩从百分制变换到等级制。
def func(score): if score>100 or score<0: return'wrong score.must between 0 and 100.' elif score>=90: return'A' elif score>=80: return'B' elif score>=70: return'C' elif score>=60: return'D' else: return'E'
4.2.4 选择结构的嵌套
选择结构可以进行嵌套来实现复杂的业务逻辑,语法如下:
if表达式1: 语句块1 if表达式2: 语句块2 else: 语句块3 else: if表达式2: 语句块4
上面语法示意中的代码层次和隶属关系如图4-4所示,图4-4代码层次与隶属关系注意相同层次的代码必须具有相同的缩进量。
使用嵌套选择结构时,一定要严格控制好不同级别代码块的缩进量,因为这决定了不同代码块的从属关系和业务逻辑是否被正确地实现,以及代码是否能够被解释器正确理解和执行。例如,前面百分制转等级制的代码,作为一种编程技巧,还可以尝试下面的写法:
def func(score): degree='DCBAAE' if score>100 or score<0: return'wrong.score must between 0 and 100.' else: index=(score-60)//10 if index>=0: return degree[index] else: return degree[-1]
4.2.5 构建跳转表实现多分支选择结构
使用列表、元组或字典可以很容易构建跳转表,在某些场合下可以更快速地实现类似于多分支选择结构的功能。例如,下面的代码根据用户输入内容的不同来调用不同的函数完成不同的功能,其中就用到了字典形式的跳转表。
funcDict={'1':lambda:print('You input 1'), '2':lambda:print('You input 2'), '3':lambda:print('You input 3')} x=input('Input an integer to call different function:') func=funcDict.get(x, None) if func: func() else: print('Wrong integer.')