標籤:出版 翻譯 關注 長度 dev 分支 from 菜鳥到高手 賦值
1.布爾(Boolean)值和布爾變數
??在講條件陳述式之前,首先應該瞭解一下布爾類型。條件陳述式(if)需要為其指定布爾值或布爾類型的變數,才能根據條件判斷是否要指定代碼塊中的語句。布爾值只有兩個值:True和False,可以將這兩個值翻譯成“真”和“假”。
??現在我們已經瞭解了布爾值是用來做什麼的,但Python語言會將哪些值看做布爾值呢?其實在Python語言中,每一種類型的值都可以被解釋成布爾類型的值。例如,下面的值都會被解釋成布爾值中的False。
None 0 "" () [] {}
??這些值所涉及到的資料類型有一些我們到現在為止並沒有講過(例如,[]表示長度為0的列表),不過讀者也不用擔心,在後面的章節會詳細講解這些資料類型。
??如果在條件陳述式中使用上面的這些值,那麼條件陳述式中的條件都會被解釋成False,也就是說,條件代碼塊中的語句不會被執行。
??在Python語言底層,會將布爾值True 看做1,將布爾值False看做0,儘管從表面上看,True和1、False和0是完全不同的兩個值,但實際上,它們是相同的。我們可以在Python控制台驗證這一點。
>>> True == 1True>>> False == 0True>>> True + False + 2021
??很明顯,我們可以直接將True看成1,False看成0,也可以直接將True和False當成1和0用,所以True + False + 20的計算結果是21。
??另外,我們可以用bool函數將其他類型的值轉換為布爾類型的值。
>>> bool("")False>>> bool("Hello")True>>> bool([])False>>> bool([1,2,3])True>>> bool(20)True>>> bool(‘‘)False
??我們可以看到,在前面給出的幾個會被系統認為是False的值,通過bool函數的轉換,會變成真正的布爾值。不過這些值是不能直接和布爾值比較的,例如,不能直接使用“[] == false”,正確的做法是先用bool函數將其轉換為布爾值,然後再比較
bool([]) == false
??在前面的代碼中使用了“==”運算子,這是邏輯運算子,是二元運算子,需要指定左右兩個運算元用於判斷兩個值是否相等,如果兩個運算元相等,運算結果為True,否則為False。這個運算子在後面的章節中會經常用到,當然,還有很多類似的運算子,在講解條件陳述式時會一起介紹。
2. 條件陳述式(if、else和elif)
??對於電腦程式來說,要學會的第一項技能就是“轉彎”,也就是根據不同的條件,執行不同的程式分支,這樣的程式才有意義。
??if語句的作用就是為程式賦予這項“轉彎”的技能。使用if語句就需要用到在3.3節介紹的代碼塊。Python語言要求當if語句的條件滿足時要執行的代碼塊必須縮排(一般是縮排4個空格)。if語句的文法格式如下:
if logic expression: # if代碼塊開始 statement1 statement2 … … statementnotherstatement # if代碼塊結束
??其中logic expression表示邏輯運算式,也就是返回布爾類型值(True或False)的運算式。由於Python語句的各種資料類型都可以作為用作布爾類型,所以logic expression可以看做是普通的運算式。根據代碼塊的規則,每一個代碼塊的開始行的結尾要使用冒號(:),如果if代碼塊結束,就會退到代碼塊開始行的縮排量即可。
??下面是if語句的基本用法。
n = 3if n == 3: print("n == 3")print("if代碼塊結束")
??在上面這段代碼中,“n == 3”是邏輯運算式,本例中的值為True。而“print("n == 3")”是if代碼塊中的語句,由於“n == 3”的值為True,所以“print("n == 3")”會被執行。最後一條語句不屬於if代碼塊,所以無論if語句的條件是否為True,這行代碼都會被執行。
??對於條件陳述式來說,往往分支不只一個。例如,上面的代碼如果變數n的值是4,那麼if語句的條件就為False,這時要執行條件為False的分支,就可以使用else子句。
n = 4if n == 3: print("n == 3")else: print("n等於其他值") print("if代碼塊結束")
??在上面這段代碼中,n等於4,所以if語句的條件為False,因此else代碼塊中的語句會被執行。if與else都是代碼塊,所以if語句和else語句後面都要以冒號(:)結尾。
??在多分支條件陳述式,需要使用elif子句設定更多的條件。elif後面跟邏輯運算式,elif也是代碼塊,所以後面要用冒號(:)結尾。另外,在if語句中,if和else部分只能有一個,而elif部分可以有任意多個。
n = 4if n == 3: print("n == 3")elif n == 4: print("n == 4")elif n == 5: print("n == 5")else: print("n等於其他值") print("if代碼塊結束")
?? 本例通過raw_input函數從控制台輸入一個名字,然後通過條件陳述式判斷名字以什麼字母開頭。
from click._compat import raw_inputname = raw_input("請輸入您的名字:") # 從控制台輸入名字if name.startswith("B"): # if代碼塊 print("名字以B開頭")elif name.startswith("F"): # elif代碼塊 print("名字以F開頭")elif name.startswith("T"): # elif代碼塊 print("名字以T開頭")else: # else代碼塊 print("名字以其他字母開頭")
??程式運行結果如所示。
3.嵌套代碼塊
??條件陳述式可以進行嵌套,也就是說,在一個條件代碼塊中,可以有另外一個條件代碼塊。包含嵌套代碼塊B的代碼塊A可以稱為B的父代碼塊。嵌套代碼塊仍然需要在父代碼塊的基礎上增加縮排量來放置自己的代碼塊。下面的例子會示範如何使用嵌套代碼塊進行邏輯判斷。
??本例要求在Python控制台輸入一個姓名,然後通過嵌套代碼塊中判斷輸入的姓名,根據判斷結果輸出結果。
name = input("你叫什麼名字?") # 從Python控制台輸入一個字串(姓名)if name.startswith("Bill"): # 以Bill開頭的姓名 if name.endswith("Gates"): # 以Gates結尾的姓名(嵌套代碼塊) print("歡迎Bill Gates先生") elif name.endswith("Clinton"): # 以Clinton結尾的姓名 print("歡迎克林頓先生") else: # 其他姓名 print("未知姓名")elif name.startswith("李"): # 以“李”開頭的姓名 if name.endswith("寧"): # 以“寧”結尾的姓名 print("歡迎李寧老師") else: # 其他姓名 print("未知姓名")else: # 其他姓名 print("未知姓名")
程式運行結果如所示。
《Python從菜鳥到高手》開始轉載了,敬請關注
4. 比較子
??儘管if語句本身的知識到現在為止已經全部講完了,不過我們的學習遠沒有介紹。前面給出的if語句的條件都非常簡單,但在實際應用中,if語句的條件可能非常複雜,這就需要使用到本節要介紹的比較子。
現在先來看看下錶列出的Python語言中的比較子。
??上標描述的比較子中,涉及到了對象和容器的概念,目前我們還沒講這些技術,在本節讀者只需瞭解Python語言可以通過比較子操作對象和容器即可,在後面介紹對象和容器的章節,會詳細介紹如何利用相關比較子操作對象和容器。
??在比較子中,最常用的就是判斷兩個值是否相等,例如,a大於b,a等於b。這些運算子包括“==”、“<”、“>”、“>=”、“<=”和“x != y”。
??如果比較兩個值是否相等,需要使用“==”運算子,也就是兩個等號。
>>> "hello" == "hello"True>>> "Hello" == "hello"False>>> 30 == 10False
??要注意,如果比較兩個字串是否相等,會比較兩個字串中對應的每一個字母,所以“Hello”和“hello”並不相等,也就是說比較子是對大小寫敏感的。
??在使用“==”運算子時一定要注意,不要寫成一個等號(=),否則就成賦值運算子了,對於賦值運算子來說,等號(=)左側必須是一個變數,否則會拋出異常。
>>> "hello" = "hello" # 使用賦值運算子,會拋出異常 File "<stdin>", line 1SyntaxError: can‘t assign to literal>>> s = "hello">>> s‘hello‘
??對於字串、數值等類型的值,也可以使用大於(>)、小於(<)等運算子比較他們的大小。
>>> "hello" > "Hello" True>>> 20 > 30False>>> s = 40>>> s <= 30False>>> "hello" != "Hello"True
??Python語言在比較字串時,會按字母ASCII順序進行比較,例如,比較“hello”和“Hello”的大小。首先會比較‘h‘和‘H‘的大小,很明顯‘h‘的ASCII大於‘H‘的ASCII,所以後面的都不需要比較了,因此,"hello" > "Hello"的結果是True。
??如果一個字串是另一個字串的首碼,那麼比較這兩個字串,Python語言會認為長的字串更大一些。
>>> "hello" < "hello world"True
??除了比較大小的幾個運算子外,還有用來確定兩個對象是否相等的運算子,以及判斷某個值是否屬於一個容器的運算子,儘管現在還沒有講到對象和容器,但這裡不妨做一個實驗,來看看這些運算子如何使用,以便以後學習對象和容器是,更容易掌握這些運算子。
??用於判斷兩個對象是否相等的運算子是is和is not,這兩個運算子看起來和等於運算子(==)差不多,不過用起來卻大有玄機。
>>> x = y = [1,2,3]>>> z = [1,2,3]>>> x == yTrue>>> x == zTrue>>> x is yTrue>>> x is zFalse>>> x is not zTrue
??在上面的代碼中,使用“==”和“is”比較x和y時結果完全一樣,不過在比較x和z時,就會體現出差異。x == z的結果是True,而x is z的結果卻是False。出現這樣的結果,原因是“==”運算子比較的是對象的值,x和z的值都是一個列表(也可以將列表看做是一個對象),並且列表中的元素個數和值完全一樣,所以x == z的結果是True。但“is”運算子用於判斷對象的同一性,也就是說,不僅對象的值要完全一樣,而且對象本身還要是同一個對象,很明顯,x和y是同一個對象,因為在賦值時,先將一個列表賦給y,然後再將y的值賦給x,所以x和y指向了同一個對象,而z另外賦值了一個列表,所以z和x、y儘管值相同,但並不是指向的同一個對象,因此,x is z的結果就是False。
??判斷某個值是否屬於一個容器,要使用“in”和“not in”運算子。下面的代碼首先定義一個列表變數x,然後判斷變數y和一些值是否屬於x。
>>> x = [1,2,3,4,5] # 定義一個列表變數>>> y = 3>>> 1 in xTrue>>> y in xTrue>>> 20 in xFalse>>> 20 not in xTrue
??“in”和“not in”運算子也可以用於判斷一個字串是否包含另外一個字串,也就是說,可以將字串看做字元或子字串的容器。
>>> s = "hello world">>> ‘e‘ in sTrue>>> "e" in sTrue>>> "x" in sFalse>>> "x" not in sTrue>>> "world" in sTrue
??如果遇到需要將多個邏輯運算式組合在一起的情況,需要用到邏輯與(and)、邏輯或(or)和邏輯非(not)。邏輯與的運算規則是只有“x and y”中的x和y都為True時,運算結果才是True,否則為False。邏輯或的運算規則是只有“x or y”中的x和y都為False時,運算結果才是False,否則都為True。邏輯非的運算規則是“not x”中,x為True,運算結果為False,x為False,運算結果為True。
>>> 20 < 30 and 40 < 50True>>> 20 > 40 or 20 < 10False>>> not 20 > 40True
??本例示範了比較子的基本用法。
print(20 == 30) # 判斷20和30是否相等,運行結果:False x = 20y = 40print(x < y) # 判斷x是否小於y,運行結果:Trueif x > y: # 條件不滿足 print("x > y")else: # 條件滿足 print("x <= y")s1 = "hello"s2 = "Hello"if s1 >= s2 and x > y: # 條件不滿足 print("滿足條件")elif not s1 < s2: # 條件滿足 print("基本滿足條件")else: # 條件不滿足 print("不滿足條件")
程式運行結果如所示。
5. 斷言(Assertions)
??斷言的使用方式類似於if語句,只是在不滿足條件時,會直接拋出異常。類似於下面的if語句(虛擬碼)
if not dondition: # 如果不滿足條件,會直接拋出異常,程式會中斷 crash program
??那麼究竟為什麼需要這樣的代碼呢?主要是因為需要監測程式在某個地方是否滿足條件,如果不滿足條件,應該及時通知開發人員,而不是將這些bug隱藏起來,直到關鍵的時刻再崩潰。
??其實在TDD(Test-driven development,測試驅動開發 )中經常使用斷言,TDD會在程式發現異常時執行斷言,並拋出異常。
在Python語言中,斷言需要使用assert語句,在assert關鍵字的後面指定斷言的條件運算式。如果條件運算式的值是False,那麼就會拋出異常。而且斷言後面的語句都不會被執行,相當於程式的一個斷點。
>>> value = 20>>> assert value < 10 or value > 30 # 條件不滿足,會拋出異常Traceback (most recent call last): File "<stdin>", line 1, in <module>AssertionError>>> assert value < 30 # 條件滿足,會正常執行後面的語句
??我們可以看到,value變數的值是20,而assert後面的條件是“value < 10 or value > 30”,很明顯,條件不滿足,所以在斷言處會拋出異常。而後面的斷言,條件是“value < 30”,這個條件是滿足的,所以在斷言後面的語句都會正常執行。
??當斷言條件不滿足時拋出異常,在預設情況下,只顯示了拋出異常的位置,並沒有顯示因為什麼拋出異常,所以為了異常資訊更明確,可以為assert語句指定異常描述。
>>> value = 20>>> assert value < 10 or value > 30, ‘value值必須在10和20之間‘ # 為斷言指定異常描述資訊Traceback (most recent call last): File "<stdin>", line 1, in <module>AssertionError: value值必須在10和20之間 # 顯示了異常描述資訊
本例示範了斷言的用法。
name = "Bill" # 定義變數nameassert name == "Bill" # 斷言條件運算式的值是True,繼續執行下面的語句age = 20 # 定義變數age# 斷言條件運算式的值是False,拋出異常,後面的代碼不會被執行assert 0 < age < 10, "年齡必須小於10歲" print("hello world") # 這行代碼不會被執行
程式運行結果如所示。
《Python從菜鳥到高手》已經出版,開始連載了,購買送視頻課程
Python從菜鳥到高手(9):條件和條件陳述式