目錄
關於這個系列
《最值得收藏的python3語法彙總》,是我爲了準備公衆號“跟哥一起學python”上面視頻教程而寫的課件。整個課件將近200頁,10w字,幾乎囊括了python3所有的語法知識點。
你可以關注這個公衆號“跟哥一起學python”,獲取對應的視頻和實例源碼。
這是我和幾位老程序員一起維護的個人公衆號,全是原創性的乾貨編程類技術文章,歡迎關注。
“數據”和“邏輯”是編程的兩個基本核心問題,高級編程語言的語法就是圍繞這兩個問題展開的。前面我們講的數據類型,就是解決“數據”的表達和處理問題。這一節我們要開始學習python語法中的控制語句,它要解決的是代碼“邏輯”問題。
發明編程語言的科學家,抽象出了兩大基本“邏輯”:條件控制邏輯和循環控制邏輯,並且設計了一套語法來實現它,這就是編程語言的控制語句。
1、條件控制語句
Python通過if語句來表達條件控制,一個最簡單的if控制語句如下:
if condition_expr:
inside_statement_block
condition_expr:是一個條件表達式。它可以是一個bool類型的值,也可以是一個可以轉換爲bool類型的值或者表達式。
inside_statement_block:是if語句內部的執行代碼塊,可以是空語句(pass),單行語句或者多行語句。當condition_expr爲True時,將執行這些語句。
-
python的縮進規則
大家注意到:上面代碼中,inside_statement_block是比if那行語句向右縮進了4個空格。這個縮進(indent)並不是爲了代碼的美觀,而是其語法規則的一部分,這是python語法比較有特色的地方。其它編程語言,比如C\JAVA,都普遍採用{}大括號來表達語句的作用域。而python則採用了縮進來達到這個目的。
大家看看下面的例子對比:
// C語言
void main(void)
{
Statement
Statement
…
if (cond)
{
Statement
Statement
…
}
statement
}
# python語言
def func(xxx):
statement
...
if cond:
statement
statement
...
statement
...
C語言是通過{}大括號來表達語句的作用域,比如我們將同屬一個函數main的語句用{}括起來。縮進規則不是C語言的語法規則,不縮進C也能正常編譯運行。縮進規則只是C語言的一個編程規範,是爲了代碼的美觀,提高可讀性。
Python是通過縮進的層次來決定作用域的,相同縮進層次的語句屬於同一作用域。比如def一個函數裏面的語句,必須採用相同的縮進層次。爲了代碼的可讀性,我們習慣性要求採用4個空格作爲一個縮進層次,如果你習慣了使用tab製表符來縮進,可以設置IDE將tab自動替換爲4個空格。如下圖是pycharm的設置方式:
實際上,不同的IDE對tab符號的顯示不一致。爲了提高代碼可讀性,4空格縮進幾乎是所有公司對編程語言的開發規範。作爲一個合格程序員,需要養成良好的編程習慣。
-
實例1:
# author: Tiger, wx ID:tiger-python
# file: ./7/7_1.py
# 實例1
if True:
pass # 空語句,佔位
a = 10
if a < 100: # 條件表達式
a += 100
print(f"value of a is : {a}")
if "abc": # 可以轉換爲bool類型的數據
print(f"condition is a string")
輸出爲:
value of a is : 110
condition is a string
python提供了pass語句,它代表一個空語句,什麼都不執行,只是佔位。比如我們想在if的條件爲True的分支裏面什麼都不執行,那麼必須寫pass語句,否則會報語法錯誤。
-
實例2
if配合else、elif,可以實現多條件分支的控制,如果連續使用elif,可以達到switch…case的相同的效果。注意,python沒有提供switch…case語句。
# 實例2
score = 80
if score > 90:
print(f"小王的成績爲優")
elif score > 70:
print(f"小王的成績爲良")
elif score > 60:
print(f"小王的成績爲及格")
else:
print(f"小王的成績爲差")
輸出爲:
小王的成績爲良
if..elif..else語句,可以不要elif,這樣就變成了if..else。它的判斷邏輯如下圖所示:
-
實例3
if控制語句是支持嵌套的,也就是說它的分支語句塊也可以是一個if控制語句。支持多層嵌套。爲了代碼可讀性,一般我們不建議嵌套的層數太多。邏輯越複雜的代碼,其可靠性肯定越差,bug越多。好的代碼,應該是簡單的、優美的。
# 實例3 , 嵌套
score = 80
if score > 60:
if score > 90:
print(f"小王的成績爲優")
elif score > 70:
print(f"小王的成績爲良")
else :
print(f"小王的成績爲及格")
else:
print(f"小王的成績爲差")
輸出爲:
小王的成績爲良
和實例2 實現的功能完全一致。
2、循環控制語句
當滿足某個條件時,代碼塊會被循環重複執行,這就是循環控制語句的使用場景。python支持for和while兩種循環控制語句。
-
for語句
for語句用於遍歷序列類型的數據,比如我們講到的字符串、列表、元組等。
其語法如下:
for variable in sequence:
for_statements_block
else:
else_statements_block
其中,variable是一個變量,會循環從sequence中獲取它的成員,並賦值給variable。for的語句塊可以直接使用variable變量。
如果sequence爲空,或者循環結束,會進入else分支執行else語句塊。注意,else是可選的,可以不要。如果沒有else,for循環完後直接結束。
它的判斷邏輯如下圖所示:
看下面的實例:
# author: Tiger, wx ID:tiger-python
# file: ./7/7_2.py
# 循環控制語句
# for,求平均數
list_1 = [100, 200, 300]
total = 0
for item in list_1:
total += item
else:
print(f"循環結束")
print(f"avg of list_1 is : {total / len(list_1)}")
輸出爲:
循環結束
avg of list_1 is : 200.0
-
range構造整數序列
有時候我們不是去循環變量一個sequence序列,而是就純粹的計數,比如從1遍歷到100。這時候需要使用range()來構造一個序列。range支持指定整數範圍,支持負數,也支持指定序列的步長。
實例如下:
# range
for incr_x in range(10):
print(incr_x, end=' ')
else:
print() # 換行
for incr_x in range(5, 10):
print(incr_x, end=' ')
else:
print() # 換行
for incr_x in range(3, 30, 3): # 支持步長
print(incr_x, end=' ')
else:
print() # 換行
for incr_x in range(-3, 10): # 支持負數
print(incr_x, end=' ')
else:
print() # 換行
輸出爲:
0 1 2 3 4 5 6 7 8 9
5 6 7 8 9
3 6 9 12 15 18 21 24 27
-3 -2 -1 0 1 2 3 4 5 6 7 8 9
-
while語句
while是另外一種常用的循環語句,它的語法規則如下:
while condition_expr:
while_statement_block
else:
else_statements_block
condition_expr是while的循環條件,可以是一個bool數值,也可以是一個條件表達式或者能轉換爲bool的數據類型。當條件爲True,則循環執行while_statement_block語句塊。當條件爲Flase,則執行else_statements_block,結束退出循環。
如執行邏輯如下圖所示:
while是通過一個條件來判斷是否進入循環,而for則必須是一個序列,所以while語句使用起來會更加靈活。但是對於序列類型來說,for會更加簡單。
如果while的條件恆爲True,那麼會進入一個死循環,除非特殊需求(比如交互式程序等待用戶輸入、網絡通信等待對端報文等),我們應避免死循環。
看下面的實例:
# while語句
cnt = 0
while cnt < 50: # 100次循環計數
cnt += 1
print(cnt, end=' ')
else:
print(f"\ncnt is {cnt}")
# 死循環
while True:
pass
輸出爲:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
cnt is 50
-
條件語句和循環語句的相互嵌套
if語句和for、while語句之間可以任意嵌套,非常靈活。
比如下面的實例:
# 嵌套
for item_1 in range(10):
for item_2 in range(item_1+1):
print(item_2, end=' ')
if item_2 == item_1:
print() # 換行
輸出爲:
0
0 1
0 1 2
0 1 2 3
0 1 2 3 4
0 1 2 3 4 5
0 1 2 3 4 5 6
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8 9
-
continue和break
某些情況下,我們希望在循環過程中,當滿足某種條件時,能強行終止循環過程,或者跳過本次循環,繼續下次循環。這是需要用到continue和break語句。
continue:跳過本次循環,繼續下次循環。
break:強行終止循環。
如下圖所示:
如下面實例:
# continue & break
# 實現列表的find功能
index = 0
list_2 = [2, 5, 6, 100, -1, 9, 88]
to_find = 9
for item in list_2:
if item == to_find:
break
index += 1
print(index)
輸出爲:
5
注意:對於多次循環嵌套的情況,continue和break只對本層循環生效。
3、推導式
推導式本來應該是數據類型章節的內容,但是因爲它涉及到if和for的語法,所以我們放到控制語句之後來講。
推導式comprehensions(又稱解析式),是Python的一種獨有特性。推導式是可以從一個序列構建另一個新的序列。 共有三種推導,在Python2和3中都有支持:
- 列表(list)推導式
- 字典(dict)推導式
- 集合(set)推導式
推導式都可以使用控制語句的方式來替代。它只是給我們提供了一種更加簡潔更加緊湊的序列生成語法。
下面我們分別介紹。
-
列表推導式
試想,如果我們要生成一個列表,這個列表裏面包含了100以內的所有能被3整除的整數,我們代碼應該怎麼寫?是的,我們可以用while循環嵌套if條件判斷的方式,如下:
# author: Tiger, wx ID:tiger-python
# file: ./9/9_8.py
# non-pythonic
list_1 = []
x = 1
while x <= 100:
if x % 3 == 0:
list_1.append(x)
x += 1
print(list_1)
輸出爲:
[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]
這個代碼沒有任何問題,如果是用慣了其它編程語言的同學第一反應就會這樣寫。但是,這種寫法是non-pythonic的。Python的程序員通常將這種具備python風格的代碼寫法稱爲pythonic,反之則non-pythonic。我們看看pythonic的寫法是這樣的:
# pythonic
list_2 = [x for x in range(1, 100) if x % 3 == 0]
print(list_2)
它實現的效果和上面是一模一樣的,是不是很簡潔很緊湊? 很pythonic。
第二種方式,就是列表的推導式。它的完整語法如下:
[x for x in data if condition]
整個表達式用中括號括起來。X是for循環中的成員,後面的if是條件判斷語句,只有滿足條件的纔會賦值給列表。前面的x也可以是一個表達式,用於在賦值前對x做一些簡單的轉換。同時,表達式中可以有多個for循環。
看下面一個實例:
# 多個for
list_3 = []
for x in [1, 2, 3]:
for y in [1, 4, 5]:
if x != y:
list_3.append((x, y))
print(list_3)
# 推導式寫法
list_3 = [(x, y) for x in [1, 2, 3] for y in [1, 4, 5] if x != y]
print(list_3)
可以看出,推導式是可以支持這種for循環嵌套的,它的邏輯和上面的普通寫法完全一致。
同樣,推導式本身也是可以嵌套的,看下面的實例:
# 推導式生成二維列表
list_4 = [[y for y in range(x*4, x*4+4)] for x in range(4)]
print(list_4)
輸出爲:
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
有時候我們也需要用到if語句的單行寫法,如下面的實例:
# if語句單行寫法
list_5 = ['hello', 100, 'xiaowang', 50]
print([x if type(x) is int else 'None' for x in list_5])
輸出爲:
['None', 100, 'None', 50]
這裏的 x if type(x) is int else 'None' 是if的單行寫法,它不只在推導式中可以使用,所有賦值語句中都可以使用,它會根據條件判斷返回一個值。
元組是沒有推導式的,我們可以生成一個列表,再強制轉換爲元組。
-
字典推導式
字典推導式的語法如下:
{ key:value for key,value in existing_data_structure }
這裏和list有所不同,因位dict裏面有兩個關鍵的屬性,key 和 value,但大同小異,我們現在的expression部分可以同時對 key 和 value 進行操作。
# author: Tiger, wx ID:tiger-python
# file: ./9/9_9.py
# 字典推導式
fruits = {'apple': 10, 'pear': 8, 'banana': 5, 'orange': 6}
dict_1 = {k.upper(): v for k, v in fruits.items()}
print(dict_1)
輸出爲:
{'APPLE': 10, 'PEAR': 8, 'BANANA': 5, 'ORANGE': 6}
這段代碼把字典中的key轉換爲大寫字母。字典推導式的結果是k:v鍵值對,所以推導式中都是對這兩個值進行操作。其方式和列表類似,我們不再展開講了。
-
集合推導式
集合推導式和列表的類似,不同在於它採用了大括號。
{ expression for item in Sequence if conditional }
既然是集合,那麼它生成的結果必須滿足集合的一些特性,比如元素必須唯一。
看下面的實例:
# 集合推導式
list_1 = ['apple', 'apple', 'Pear', 'ORANGE', 'banANA']
set_1 = {x.upper() for x in list_1}
print(set_1)
輸出爲:
{'ORANGE', 'PEAR', 'BANANA', 'APPLE'}
可以看到,對於重複的元素‘apple’,集合推導式會自動去重。