3.1.2 选择结构的几种形式
选择结构通过判断某些特定条件是否满足来决定下一步的执行流程,是非常重要的控制结构。常见的有单分支选择结构、双分支选择结构、多分支选择结构以及嵌套的分支结构,形式比较灵活多变,具体使用哪一种最终还是取决于要实现的业务逻辑。循环结构和异常处理结构中也可以带有else子句,也可以看作是特殊形式的选择结构。
1 单分支选择结构
单分支选择结构是最简单的一种形式,其语法如下所示,其中表达式后面的冒号“:”是不可缺少的,表示一个语句块的开始,后面几种其他形式的选择结构和循环结构中的冒号也是必须要有的。
if 表达式:
语句块
当表达式值为True或其他等价值时,表示条件满足,语句块将被执行,否则该语句块将不被执行,继续执行后面的代码(如果有)。
1 >>> x = input('Input two numbers:')
2 Input two numbers: 3 4
3 >>>
4 >>> a,b = map(int,x.split())
5 >>>
6 >>> a
7 3
8 >>> b
9 4
10 >>>
11 >>> if b > a:
12 a,b = b,a #序列解包,交换两个变量的值
13
14
15 >>> print(a,b)
16 4 3
17 >>>
注意:在Python中,代码的缩进非常重要,缩进是体现代码逻辑关系的重要方式,同一个代码块必须保证相同的缩进量。养成习惯,严格遵循这个要求吧。
2 双分支选择结构
双分支选择结构的语法为:
if 表达式:
语句块 1
else:
语句块 2
当表达式值为True或其他等价值时,执行语句块 1 ,否则执行语句块 2。代码示例如下:
1 l = [ '1','2','3','4','5' ]
2
3 if l:
4 print(l)
5 else:
6 print('Empty')
7
8
9 # 执行结果:['1', '2', '3', '4', '5']
拓展知识:Python还提供了一个三元运算符,可以实现与选择结构相似的效果。语法为:
value1 if condition else value2
当条件表达式condition的值与True等价时,表达式的值为 value1,否则表达式的值为 value2。另外,value1 和 value2本身也可以是复杂表达式,也可以包含函数调用。下面的代码演示了上面的表达式的用法,可以看出,这个结构的表达式也具有惰性求值的特点。
1 >>> a = 5
2 >>> print(6) if a > 3 else print(5)
3 6
4 >>>
5 >>> print(6 if a > 3 else 5) #注意,虽然结果与上一行代码一样,但代码含义不同
6 6
7 >>>
8 >>> b = 6 if a > 13 else 9 #赋值运算符优先级低
9 >>> b
10 9
11 >>>
12 >>>
13 >>> import math
14 >>> x = math.sqrt(9) if 5 > 3 else random.randint(1,100)
15 >>> x
16 3.0
17 >>>
18 >>> #三目运算符就这样简单地用用就好了,,
3 多分支选择结构
多分支选择结构为用户提供了更多的选择,可以实现复杂的业务逻辑,多分支选择结构的语法为:
if 表达式 1:
语句块 1
elif 表达式 2:
语句块 2
elif 表达式 3:
语句块3
...
else:
语句块 n
其中,关键字 elif 是 else if的缩写。下面的代码演示了如何利用多分支选择结构将成绩从百分制转换到等级制。
1 def func(score):
2 if score > 100:
3 return 'wrong score.mut <= 100'
4 elif score >= 90:
5 return 'A'
6 elif score >= 80:
7 return 'B'
8 elif score >= 70:
9 return 'C'
10 elif score >= 60:
11 return 'D'
12 elif score >= 0:
13 return 'E'
14 else:
15 return 'wrong score.must > 0'
16
17 l = [120,99,87,62,3,-10]
18
19 for s in l:
20 print('# your score is : {} , the result is :{}'.format(s,func(s)))
21
22 # your score is : 120 , the result is :wrong score.mut <= 100
23 # your score is : 99 , the result is :A
24 # your score is : 87 , the result is :B
25 # your score is : 62 , the result is :D
26 # your score is : 3 , the result is :E
27 # your score is : -10 , the result is :wrong score.must > 0
4 选择结构的嵌套
选择结构可以进行嵌套来表达复杂的业务逻辑,语法如下:
if 表达式 1:
语句块 1
if 表达式 2:
语句块 2
else:
语句块 3
else:
if 表达式 4:
语句块 4
使用嵌套选择结构是,一定要严格控制好不同级别代码块的缩进量,因为这决定了不同代码块的从属关系和业务逻辑是否被正确的实现,以及代码是否能够被Python正确理解和执行。例如,前面百分之转等级制的代码,作为一种编程技巧,开可以尝试下面的写法:
1 def func(score):
2 degree = 'DCBAAE'
3 if score > 100 or score < 0:
4 return 'wrong score.nust between 0 and 100.'
5 else:
6 index = (score -60) // 10
7 if index >= 0:
8 return degree[index],index
9 else:
10 return degree[-1],index
11
12
13 l = [-10,30,50,60,93,100]
14
15 for s in l:
16 print('# your score is : {} , the result is :{}'.format(s,func(s)))
17
18 # your score is : -10 , the result is :wrong score.nust between 0 and 100.
19 # your score is : 30 , the result is :('E', -3)
20 # your score is : 50 , the result is :('E', -1)
21 # your score is : 60 , the result is :('D', 0)
22 # your score is : 93 , the result is :('A', 3)
23 # your score is : 100 , the result is :('A', 4)
建议:在编写条件表达式时,建议适当使用括号,这样可以更准确地表达业务逻辑,同时提高代码可读性。
案例:用户输入若干个成绩,求所有成绩的平均分。每输入一个成绩后询问是否继续输入下一个成绩,回答yes就继续输入下一个成绩,回答no就停止输入成绩。
我的实现过程:
1 l = []
2 while True:
3 num = input('请输入一门成绩成绩范围为0-100')
4 if int(num) > 100 or int(num) < 0:
5 print('您输入的成绩不合法,请重新开始输入')
6
7 else:
8 l.append(int(num))
9
10 xz = input('是否继续输入成绩 yes/no')
11
12 if xz.lower() not in ('yes','no'):
13 print('请输入正确的答案,yes / no')
14
15 elif xz.lower() == 'yes':
16 num = input('请输入一门成绩成绩范围为0-100 2')
17 if int(num) > 100 or int(num) < 0:
18 print('您输入的成绩不合法,请重新开始输入')
19 l.append(int(num))
20 xz2 = input('是否继续输入成绩 yes/no 2')
21
22 if xz2.lower() not in ('yes','no'):
23 print('请输入正确的答案,yes / no')
24 elif xz2.lower() == 'yes':
25 pass
26 elif xz2.lower() == 'no':
27 break
28
29 elif xz.lower() == 'no':
30 break
31
32 print(sum(l) / len(l))
作者的实现过程:
1 # 案例:用户输入若干个成绩,求所有成绩的平均分。每输入一个成绩后询问是否继续输入下一个成绩,回答yes就继续输入下一个成绩,回答no就停止输入成绩。
2
3 numbers = []
4
5 while True:
6 x = input('请输入一个0-100的整数:')
7 try:
8 if int(x) > 100 or int(x) < 0:
9 print('您输入的成绩不合法')
10 break
11 else:
12 numbers.append(int(x))
13 except:
14 print('不是整数')
15 while True:
16 flag = input('继续输入吗?(yes/no)')
17 if flag.lower() not in ('yes', 'no'):
18 print('只能输入 yes 或 no')
19 else:
20 break
21
22 if flag.lower() == 'no':
23 break
24
25 print(sum(numbers) / len(numbers))
案例:编写程序,判断今天是今年的第几天。
1 import time
2
3 date = time.localtime() #获取当前日期时间
4 year,month,day = date[:3]
5 day_month = [31,28,31,30,31,30,31,31,30,31,30,31]
6
7 if year % 400 == 0 or (year%4 == 0 and year%100 !=0): #判断是否为闰年,如果闰年,2月有29天
8 day_month[1] = 29
9
10 if month == 1:
11 print(day)
12 else:
13 print(sum(day_month[:month - 1]) + day)
14
15 #74
拓展知识:Python标准库datetime。这个标准库提供了timedelta对象可以很方便地计算指定年、月、日、时、分、秒之前或之后的日期时间,还提供了返回结果中包含“今天是今年第几天”、“今天是本周第几天”等答案的 timetuple()函数,等等。
1 >>> import datetime
2 >>> today = datetime.date.today()
3 >>>
4 >>> today
5 datetime.date(2018, 3, 15)
6 >>>
7 >>> today.timetuple().tm_yday
8 74
9 >>> #今天是今年的第几天
10 >>>
11 >>> today.timetuple().tm_mday
12 15
13 >>> #今天是本月的第几天
14 >>>
15 >>> today.timetuple().tm_wday
16 3
17 >>> #今天是本周的第几天
18 >>>
19 >>> today.replace(year = 2013)
20 datetime.date(2013, 3, 15)
21 >>>
22 >>> #替换日期中的年
23 >>>
24 >>> today.replace(month = 1) #替换日期中的月
25 datetime.date(2018, 1, 15)
26 >>>
27 >>> today.replace(day = 6) #替换日期中的日
28 datetime.date(2018, 3, 6)
29 >>>
30 >>> #可以看出上述3个替换并不是改变today
31 >>>
32 >>>
33 >>> #获取现在的时间点
34 >>> now = datetime.datetime.now()
35 >>> now
36 datetime.datetime(2018, 3, 15, 17, 27, 48, 361247)
37 >>>
38 >>> now.replace(second=30) #替换now中的秒数
39 datetime.datetime(2018, 3, 15, 17, 27, 30, 361247)
40 >>>
41 >>>
42 >>>
43 >>> now + datetime.timedelta(days = 5) #计算5天后的日期
44 datetime.datetime(2018, 3, 20, 17, 27, 48, 361247)
45 >>>
46 >>> now + datetime.timedelta(days = -6) #计算6天前的日期
47 datetime.datetime(2018, 3, 9, 17, 27, 48, 361247)
48 >>>
49 >>> #大家拓展一下,,计算一个小时前后应该怎么写呢?
50 >>>
拓展知识:标准库 calendar 也提供了一些与日期操作有关的方法。例如:
1 >>> import calendar #导入模块
2 >>> print(calendar.calendar(2018)) #查看2018年日历
3 2018
4
5 January February March
6 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
7 1 2 3 4 5 6 7 1 2 3 4 1 2 3 4
8 8 9 10 11 12 13 14 5 6 7 8 9 10 11 5 6 7 8 9 10 11
9 15 16 17 18 19 20 21 12 13 14 15 16 17 18 12 13 14 15 16 17 18
10 22 23 24 25 26 27 28 19 20 21 22 23 24 25 19 20 21 22 23 24 25
11 29 30 31 26 27 28 26 27 28 29 30 31
12
13 April May June
14 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
15 1 1 2 3 4 5 6 1 2 3
16 2 3 4 5 6 7 8 7 8 9 10 11 12 13 4 5 6 7 8 9 10
17 9 10 11 12 13 14 15 14 15 16 17 18 19 20 11 12 13 14 15 16 17
18 16 17 18 19 20 21 22 21 22 23 24 25 26 27 18 19 20 21 22 23 24
19 23 24 25 26 27 28 29 28 29 30 31 25 26 27 28 29 30
20 30
21
22 July August September
23 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
24 1 1 2 3 4 5 1 2
25 2 3 4 5 6 7 8 6 7 8 9 10 11 12 3 4 5 6 7 8 9
26 9 10 11 12 13 14 15 13 14 15 16 17 18 19 10 11 12 13 14 15 16
27 16 17 18 19 20 21 22 20 21 22 23 24 25 26 17 18 19 20 21 22 23
28 23 24 25 26 27 28 29 27 28 29 30 31 24 25 26 27 28 29 30
29 30 31
30
31 October November December
32 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
33 1 2 3 4 5 6 7 1 2 3 4 1 2
34 8 9 10 11 12 13 14 5 6 7 8 9 10 11 3 4 5 6 7 8 9
35 15 16 17 18 19 20 21 12 13 14 15 16 17 18 10 11 12 13 14 15 16
36 22 23 24 25 26 27 28 19 20 21 22 23 24 25 17 18 19 20 21 22 23
37 29 30 31 26 27 28 29 30 24 25 26 27 28 29 30
38 31
39
40 >>>
41 >>>
42 >>> print(calendar.month(2018,3)) #查看2018年3月的日历表
43
44 March 2018
45 Mo Tu We Th Fr Sa Su
46 1 2 3 4
47 5 6 7 8 9 10 11
48 12 13 14 15 16 17 18
49 19 20 21 22 23 24 25
50 26 27 28 29 30 31
51
52 >>>
53 >>> calendar.isleap(2018) #判断2018年是否为闰年
54 False
55 >>>
56 >>>
57 >>> calendar.weekday(2016,4,26) #查看指定日期是周几
58 1
59 >>>
60 >>>
拓展知识:也可以自己编写代码模拟Python标准库calendar中查看日历的方法。--讲真,这部分代码我看不懂,先跟着敲一遍,董老师也说了,这本书要多学几遍的。
1 from datetime import date
2
3 daysOfMonth = [31,28,31,30,31,30,31,31,30,31,30,31]
4
5 def myCalendar(year,month):
6
7 #获取year年month月1日是周几
8 start = date(year,month,1).timetuple().tm_wday
9
10 #打印头部信息
11 print('{0}年{1}月日历'.format(year,month).center(56))
12 print('\t'.join('日 一 二 三 四 五 六'.split()))
13
14 #获取该月有多少天如果是2月并且是闰年,适当调整一下
15 day = daysOfMonth[month -1]
16
17 if month == 2:
18 if year % 400 == 0 or(year % 4 ==0 and year % 100 != 0):
19 day += 1
20
21 #生成数据,需要根据在前面填充空白
22 result = ['' * 8 for i in range(start + 1)]
23 result += list(map(lambda d:str(d).ljust(8),range(1,day + 1)))
24
25 #打印数据
26 for i,day in enumerate(result):
27 if i != 0 and i % 7 == 0:
28 print()
29 print(day,end='')
30 print()
31
32 def main(year,month = -1):
33 if type(year) != int or year < 1000 or year > 10000:
34 print('Year error')
35 return
36
37 if type(month) == int:
38 #如果没有指定月份,就打印全年的日历
39 if month == -1:
40 for m in range(1,13):
41 myCalendar(year,m)
42
43 #如果指定了月份,就只打印这一个月的日历
44 elif month in range(1,13):
45 myCalendar(year,month)
46 else:
47 print('Month error')
48 return
49 else:
50 print('Month error')
51 return
52
53
54 main(2017)