選擇結構通過判斷某些特定條件是否滿足來決定下一步的執行流程,是非常重要的控制結構。常見的有單分支選擇結構、雙分支選擇結構、多分支選擇結構以及嵌套的分支結構,形式比較靈活多變,具體使用哪一種最終還是取決於要實現的業務邏輯。循環結構和異常處理結構中也可以帶有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)