也能掌握條件判斷與分支邏輯)
很多剛開始學(xué)Python的朋友學(xué)到if語句時都會有一種“好像看懂了但自己一寫就亂”的感覺。這篇文章是我自己學(xué)習(xí)過程的第4篇記錄專門把if語句這塊從頭到尾理了一遍。我不打算講一堆官方文檔里那種干巴巴的定義而是把if語句到底是什么、為什么需要它、寫的時候哪里最容易翻車以及怎么在真實場景里把它用好一次性講清楚。如果你是零基礎(chǔ)剛?cè)腴T或者學(xué)了一兩個星期還處于“看得懂但寫不出”的狀態(tài)這篇文章應(yīng)該能幫你把if語句這一關(guān)徹底打通。1. 先別急著寫代碼if語句解決的到底是什么問題1.1 從“順序執(zhí)行”到“按條件執(zhí)行”的思維轉(zhuǎn)變學(xué)if語句之前你寫的Python代碼基本都是從上往下一條一條執(zhí)行就像按照菜譜做菜第一步切菜、第二步熱鍋、第三步倒油順序不能亂。這種“順序結(jié)構(gòu)”是所有程序的基礎(chǔ)但問題是——現(xiàn)實世界根本不按劇本走。舉個例子你寫了一個程序讓用戶輸入年齡然后輸出“可以進入網(wǎng)吧”。如果用戶今年10歲呢程序還是會老老實實輸出“可以進入網(wǎng)吧”這顯然就出問題了。因為程序缺少一個最核心的能力判斷。它沒辦法根據(jù)不同的輸入做出不同的反應(yīng)。if語句就是用來解決這個問題的。它讓程序擁有了一個簡單的“大腦”可以根據(jù)條件是否成立決定下一步執(zhí)行哪段代碼。換句話說if語句是程序從“死板地執(zhí)行”走向“智能地決策”的第一步。這其實是編程思維里非常重要的一次轉(zhuǎn)變。在學(xué)if之前你的代碼里只有一條直線學(xué)完if之后你的代碼會出現(xiàn)分岔路口程序會像一個路口的交警一樣判斷來車方向后決定放行哪條路。1.2 條件判斷在真實程序里的幾個典型場景理解了if的本質(zhì)是“按條件分流”之后你會發(fā)現(xiàn)它的應(yīng)用場景幾乎無處不在。我簡單列幾個最常見的場景你會發(fā)現(xiàn)這些場景里都能看到if的影子表單校驗用戶注冊時輸入了郵箱程序需要檢查輸入的內(nèi)容里是否包含“”和“.”不包含就提示格式錯誤。權(quán)限控制用戶嘗試刪除一篇文章程序要先判斷當(dāng)前登錄的用戶是不是文章作者不是就拒絕操作并提示“無權(quán)限”。業(yè)務(wù)規(guī)則電商系統(tǒng)計算訂單金額時一次下單滿300元才可以使用優(yōu)惠券金額不足就按原價結(jié)算。程序自我保護讀取文件前先判斷文件是否存在存在才嘗試打開避免程序因報錯直接崩潰。這些場景如果不用if你只能把所有情況都當(dāng)成同一種情況來處理那程序就不可能正確應(yīng)對變化的輸入。所以也可以說如果你發(fā)現(xiàn)自己寫的程序經(jīng)常“不分青紅皂白”地執(zhí)行所有流程大概率就是該引入條件判斷了。2. 寫一個最簡單的if縮進、冒號與代碼塊的底層邏輯2.1 逐行解讀一個最基本的if判斷光說不練沒有意義直接看代碼。這是一個最簡單的if語句age 18 if age 18: print(你已經(jīng)成年了)這段代碼的運行邏輯其實就兩句話先判斷age 18是否成立如果成立就執(zhí)行下面縮進的代碼。但這里有兩個非常容易被新手忽略的細(xì)節(jié)第一if后面有一個冒號。這個冒號就像是在說“我要開始陳述滿足這個條件時該做的事了”后面的代碼需要換行并向右縮進。很多初學(xué)者會漏掉這個冒號然后程序直接報SyntaxError。第二print這一行前面有縮進。Python是一個非常依賴縮進的語言縮進不僅是為了讓代碼好看它直接決定了哪些代碼屬于這個if條件。如果print語句沒有縮進它就變成了無條件執(zhí)行的普通代碼if判斷就形同虛設(shè)了。你可以試著把縮進去掉運行一下這段代碼age 18 if age 18: print(你已經(jīng)成年了)這時Python會直接報錯IndentationError: expected an indented block after if statement。這就是縮進在Python中的強制力。2.2 縮進規(guī)則與代碼塊的通俗理解很多新手不理解“代碼塊”這個概念。我換個說法你就明白了代碼塊就是“被同一個if條件管住的一組動作”。比如下雨天出門你的思考過程是如果下雨我就帶傘、穿雨靴、換一條不怎么怕水的路線。這個“帶傘、穿雨靴、換路線”就是同一個條件下一起執(zhí)行的三件事。在Python中這三件事要寫在一起并且保持相同層級的縮進is_raining True if is_raining: print(帶上雨傘) print(穿上雨靴) print(換一條路線)注意print(“帶上雨傘”)、print(“穿上雨靴”)、print(“換一條路線”)這三行代碼擁有完全相同的縮進層級它們構(gòu)成了一個代碼塊。只要is_raining為True這三行代碼就會依次執(zhí)行如果為False這三行代碼一行都不會執(zhí)行。這個“一起執(zhí)行”的概念非常重要因為如果你不小心把其中一行往左或往右多縮進了一點它可能就不再屬于這個條件了。Python的縮進標(biāo)準(zhǔn)是4個空格但統(tǒng)一用Tab也行——只要你全程保持一致。千萬別混用空格和Tab否則你會陷入非常折磨人的TabError。2.3 布爾值if判斷背后真正的“開關(guān)”if后面跟的那個條件不管寫得多復(fù)雜最終都會被Python解釋成一個值True或者False。在Python里這兩個值叫作布爾值(Boolean)它們是條件判斷的底層機制。比如age 18這個表達式它運行完的結(jié)果就是True或False并不會真的輸出這句話。你可以自己在Python里驗證一下age 18 result (age 18) print(result) # 輸出 True甚至可以這樣理解if語句本質(zhì)上就是一個開關(guān)判斷條件為True開關(guān)就閉合代碼塊通電運行條件為False開關(guān)就斷開代碼塊不運行。這里還有一個初學(xué)者經(jīng)常過的坎——Python中的“真”和“假”不只是True和False。在某些情況下0、空字符串、空列表[]、空字典{}、None等值在條件判斷中也會被當(dāng)作“假”而任何非0數(shù)字、非空字符串、非空容器都會被當(dāng)作“真”。這個知識點以后你會頻繁遇到這里先記住結(jié)論即可。3. 判斷條件從哪來比較運算、邏輯運算與成員判斷的配合3.1 比較運算符最樸素的判斷工具if語句最常見的判斷來源就是比較運算符它們用來比較兩個值的關(guān)系最終得到一個布爾值運算符含義示例結(jié)果(當(dāng)x10時)等于x 10True!不等于x ! 5True大于x 5True小于x 20True大于等于x 10True小于等于x 9False這里最需要提醒新手的是判斷兩個值是否相等用的是雙等號不是單等號。單等號是賦值操作意思是“把右邊的值裝進左邊的變量”。如果你在if條件里寫成if x 10:Python會直接報語法錯誤因為在條件判斷里不允許進行賦值操作。我自己剛開始學(xué)的時候就犯過這個錯誤怎么都想不通為什么Python一直報錯。后來才明白雙等號是“問”單等號是“給”。一個是比較一個是賦值很像你把“這個變量是不是等于10”錯寫成了“讓這個變量等于10”。3.2 邏輯運算符處理“多個條件同時滿足或任選其一”的場景現(xiàn)實世界的判斷很少只有一個條件常常是復(fù)合判斷。比如去游樂園需要“身高滿1.2米并且沒有恐高癥”才能坐過山車。這就要用到邏輯運算符。Python的邏輯運算符有三個and、or、not。and兩邊都為True結(jié)果才是True。類比“并且”。or只要有一邊為True結(jié)果就是True。類比“或者”。not取反。本來是Truenot一下就變成False。來看一個完整的例子height 1.3 has_phobia False if height 1.2 and not has_phobia: print(可以乘坐過山車) else: print(暫時不能乘坐過山車)這個程序的判斷邏輯拆開來看是這樣的先看身高是否滿1.2米為True再看has_phobia是False那么not has_phobia就是True兩個True通過and連接最終條件為True于是輸出“可以乘坐過山車”。這里推薦一種自查方式遇到復(fù)雜的條件時把各個子條件的真假先在旁邊標(biāo)出來再從左到右推導(dǎo)最終結(jié)果。剛學(xué)的時候慢一點沒關(guān)系熟練后一眼就能看出結(jié)果。3.3 成員運算符用in判斷某個值是否在容器里除了比較數(shù)值和邏輯運算還有一個在真實寫代碼時出場率極高的判斷方式——成員判斷in。比如你想判斷“apple”是否在一個水果列表里fruits [apple, banana, orange] if apple in fruits: print(列表里有蘋果)再比如判斷一個字符串里是否包含某個關(guān)鍵詞title Python零基礎(chǔ)入門教程 if Python in title: print(這是一篇Python相關(guān)的文章)in判斷的底層邏輯是遍歷容器逐個檢查是否存在目標(biāo)元素。對初學(xué)者來說先會用它處理列表和字符串就夠了。它和的區(qū)別在于是判斷兩個對象是否相等in是判斷“一個東西”是否存在于“一個大容器”中。比如apple fruits是在問“apple字符串是不是等于整個列表”結(jié)果顯然是False而apple in fruits才是問“apple是不是在fruits列表里”結(jié)果才是True。4. 讓程序?qū)W會“二選一”if-else結(jié)構(gòu)實測4.1 為什么必須要有else前面寫的例子都是“如果滿足條件就執(zhí)行某些操作”那如果不滿足條件呢程序什么都不做。但實際應(yīng)用中很多時候我們需要“滿足條件是做A不滿足條件時至少做B”。比如登錄場景用戶名和密碼正確就進入首頁不正確就要提示“登錄失敗”。如果不滿足條件時什么也不做用戶會以為自己沒點登錄按鈕體驗非常糟糕。這時候就需要else出場了。它的意思很直白如果if條件不成立就走else這條分支。4.2 if-else完整運行邏輯與代碼演示來看一個可以直接運行驗證的程序password input(請輸入密碼) if password python123: print(密碼正確正在進入系統(tǒng)...) else: print(密碼錯誤請重新輸入)這個程序雖然簡單但它已經(jīng)具備了真實的決策能力。程序先從input函數(shù)讀取用戶輸入存到password變量中。拿到用戶的輸入之后if判斷這個字符串是否等于“python123”等于就走第一條分支不等于就走else分支。這里有一個細(xì)節(jié)值提一下input函數(shù)得到的永遠(yuǎn)是字符串類型。如果用戶輸入數(shù)字后面拿這個輸入去和整數(shù)比較時就需要先做類型轉(zhuǎn)換。比如age input(請輸入你的年齡) age int(age) # 把字符串轉(zhuǎn)成整數(shù) if age 18: print(成年人) else: print(未成年人)如果不寫int(age)這一步直接用字符串和數(shù)字18比較Python在Python 3里會直接拋TypeError。這也是新手最容易踩的坑之一——input返回的是字符串一定要記得根據(jù)場景做轉(zhuǎn)換。4.3 一個快速判斷“if還是else”的小技巧很多新手寫if-else的時候會糾結(jié)哪段邏輯放if里哪段放else里我的判斷習(xí)慣很簡單把“正常情況”或“最常見的情況”放到if里把“異常情況”或“兜底處理”放到else里。比如判斷用戶是否登錄成功成功是正常情況放if失敗是異常情況放else。判斷文件是否存在存在是正常路徑放if不存在提示錯誤放else。這樣寫出來的代碼可讀性更好別人看代碼時一眼就能看出程序的“主流程”是什么。反之如果把主流程塞到else里讀代碼的人很容易被繞暈。5. 多個分支怎么辦elif讓程序擁有更多選擇路徑5.1 從if-else到elif一種更清晰的表達方式現(xiàn)實生活中的判斷遠(yuǎn)不止“要么A要么B”這么簡單。比如成績評定90分以上是優(yōu)秀80到89是良好70到79是中等60到69是及格60分以下是不及格。這種多選一的情況如果只用if和else寫你得嵌套好幾層代碼會變得很難讀。Python提供了elif它是“else if”的縮寫。看下面的代碼score 85 if score 90: print(優(yōu)秀) elif score 80: print(良好) elif score 70: print(中等) elif score 60: print(及格) else: print(不及格)這段代碼讀起來非常順暢如果成績大于等于90輸出優(yōu)秀否則再判斷是否大于等于80滿足則輸出良好……以此類推。程序會從上到下依次檢查每個條件一旦發(fā)現(xiàn)某個條件成立執(zhí)行完對應(yīng)的代碼塊后就會跳過整個if-elif-else結(jié)構(gòu)的剩余部分不會再繼續(xù)往下判斷了。這是一個非常關(guān)鍵的執(zhí)行邏輯多個elif分支中最多只會有一個分支被執(zhí)行。比如score為85第一個條件score 90不成立進入到第二個條件score 80成立輸出“良好”之后整段代碼結(jié)束后面的elif和else都不會再執(zhí)行。5.2 elif與多個獨立if的差別一個性能與正確性并存的問題有些新hand可能會想那我不用elif全用獨立的if不也行嗎比如score 85 if score 90: print(優(yōu)秀) if score 80: print(良好) if score 70: print(中等) if score 60: print(及格) if score 60: print(不及格)結(jié)果會怎樣運行之后你會發(fā)現(xiàn)分?jǐn)?shù)85居然同時輸出了“良好”“中等”“及格”三行。原因很簡單每個if都是獨立的判斷程序從頭到尾把每個條件都檢查了一遍。85當(dāng)然大于等于80也大于等于70也大于等于60所以三個條件都成立三個代碼塊都執(zhí)行了。所以在“多選一”的場景下必須使用elif而不是多個獨立if。elif把多個條件串聯(lián)成一個互斥的整體就像“這些路線你只能走一條走了一條后面就全不走了”。用獨立if時程序像個不設(shè)防的關(guān)卡每個入口都放行路徑全都會走一遍。這種差異不僅是代碼美觀問題更是邏輯上有沒有bug的問題。5.3 多分支判斷的執(zhí)行順序一門容易被忽略的必修課elif雖然好用但條件的順序是很有講究的。看這個常見的錯誤寫法score 95 if score 60: print(及格) elif score 80: print(良好) elif score 90: print(優(yōu)秀)問題出在哪score等于95時第一個判斷score 60就成立了直接輸出“及格”根本輪不到后面的“良好”和“優(yōu)秀”。因為程序一旦找到一個成立的條件就會立刻結(jié)束整個判斷鏈。寫多分支時一定要把范圍更小的條件放在前面。比如成績評定“ 90”是最高檔你應(yīng)該先判斷它。一個簡單的自查辦法是實際代入幾個邊界值比如60、69、70、79、80、89、90從頭到尾推一遍看輸出是否符合預(yù)期。6. 分支嵌套復(fù)雜場景的if進階用法與可讀性取舍6.1 嵌套if的真實應(yīng)用場景有些業(yè)務(wù)場景里一個大前提下還要做更細(xì)的判斷。比如網(wǎng)站后臺有一個管理員操作執(zhí)行刪除用戶的操作前先判斷當(dāng)前用戶是否已登錄已登錄的情況下再判斷是否具備管理員權(quán)限。這種“先過一關(guān)再過第二關(guān)”的邏輯用嵌套if來實現(xiàn)非常自然。來看一個更接近真實業(yè)務(wù)的代碼示例is_login True is_admin True username test_user target_user someone if is_login: if username target_user or is_admin: print(允許刪除該用戶) else: print(沒有刪除權(quán)限) else: print(請先登錄)這種寫法的邏輯是清晰的只有外層條件成立才會進入內(nèi)層再做進一步判斷。這個結(jié)構(gòu)非常適合表達層層遞進的業(yè)務(wù)規(guī)則。6.2 嵌套的正確寫法與常見格式錯誤嵌套的關(guān)鍵在于縮進層級。外層if的代碼塊縮進4個空格內(nèi)層if要在這個基礎(chǔ)上再縮進4個空格也就是一共8個空格??创a時內(nèi)層if通過更深的縮進表示“我是在外層里的”。寫嵌套代碼時最容易犯的格式錯誤是忘記為外層if補else分支。假如用戶沒登錄你希望程序至少提示一句“請先登錄”但如果外層只寫了if沒有else那用戶沒登錄時整段代碼會直接靜默結(jié)束看起來就像程序沒有任何反應(yīng)。另外我強烈建議嵌套深度最多不要超過3層。超過3層以后代碼的可讀性和可維護性會急劇下降。你自己可能還看得懂但過一周再看就未必了。如果業(yè)務(wù)確實需要很深的分層可以考慮用后面的優(yōu)化方式改寫而不是一路嵌套到底。6.3 嵌套與elif的搭配策略如何保持邏輯清晰嵌套和elif并不沖突在業(yè)務(wù)復(fù)雜時它們經(jīng)常混合使用。外層判斷大前提內(nèi)層用elif處理細(xì)分的多種情況。比如下面這個例子外賣配送費計算。會員和非會員大前提不同會員里又分黃金會員和普通會員is_member True member_level gold order_amount 150 if is_member: if member_level gold and order_amount 100: print(免配送費) elif member_level silver: print(配送費減半) else: print(配送費5元) else: if order_amount 300: print(免配送費) else: print(配送費8元)這種寫法讀起來思路清晰先區(qū)分會員和非會員兩大陣營再在各自陣營內(nèi)根據(jù)不同條件做二次分配。寫分支邏輯時最忌諱的是把所有條件都攤平在一個大if里強行靠and拼接那樣十個條件擠在一起看著都頭疼。另外我分享一個小習(xí)慣寫完嵌套后會立刻檢查每個if是不是都有對應(yīng)的else。如果確實不需要else那就明確注釋說明“此條件不成立時無需處理”。否則一旦代碼出錯空走的分支會讓你排查起來非常痛苦。7. 容易搞混的幾種判斷條件類型從int到str再到None7.1 字符串比較等值判斷之外還有大小和包含關(guān)系字符串之間可以用判斷內(nèi)容是否完全一致可以用!判斷是否不同也可以直接用或進行字典序比較但初級階段更常用的場景是判斷一段內(nèi)容是否包含某個關(guān)鍵詞。比如在一個用戶反饋頁面你需要判斷用戶輸入的內(nèi)容是否含有敏感詞content 這里是一段普通的用戶反饋內(nèi)容 if 廣告 in content: print(內(nèi)容中包含疑似廣告信息需要人工審核) elif 詐騙 in content: print(內(nèi)容嚴(yán)重違規(guī)禁止發(fā)布) else: print(內(nèi)容檢查通過)使用in判斷字符串時它是區(qū)分大小寫的。如果需要不區(qū)分大小寫地判斷可以先把雙方都轉(zhuǎn)成小寫或大寫再比較keyword PYTHON if keyword.lower() python.lower(): print(兩個字符串在不區(qū)分大小寫的情況下相同)7.2 數(shù)值比較中的邊界條件與浮點數(shù)陷阱數(shù)值比較看似簡單但有兩個小坑值得注意。第一個坑是邊界值的取舍。比如判斷年齡“18歲及以上”和“18歲以上”分別對應(yīng) 18和 18。一個“含”一個“不含”差一個等號業(yè)務(wù)語義完全不同。現(xiàn)實校驗中這往往對應(yīng)不同的場景寫之前要把邊界條件想清楚否則容易誤判。第二個坑是浮點數(shù)比較的誤差。比如判斷0.1 0.2 0.3在Python里運行結(jié)果是False。這是因為計算機用二進制存儲小數(shù)時0.1和0.2都存在無法精確表示的精度誤差導(dǎo)致結(jié)果不是0.3。以后遇到浮點數(shù)比較時別直接用更好的做法是判斷兩個數(shù)的差值是否小于一個很小的數(shù)比如abs(0.1 0.2 - 0.3) 1e-9。7.3 判斷變量是否為None的正確姿勢在Python中None是一個特殊的值表示“沒有值”或“空”。在很多場景下比如函數(shù)沒有返回結(jié)果、某個可選參數(shù)沒傳變量就會是None。判斷一個變量是否為None官方推薦的方法是is None和is not None而不是用 None。看這個例子result get_data() # 假設(shè)這個函數(shù)可能返回None if result is not None: print(獲取數(shù)據(jù)成功) print(result) else: print(獲取數(shù)據(jù)失敗返回了空值)推薦用is而不是的原因在于is比較的是身份也就是“是否是同一個對象”而None在Python中是一個唯一的單例對象所以用is判斷既準(zhǔn)確又高效。使用雖然通常也能達到目的但從語義上看不夠嚴(yán)謹(jǐn)。7.4 用bool()判斷“真假值”的隱藏規(guī)律前面提到Python中有些值會被當(dāng)作“假”來處理。這個特性在真實場景中很實用如果你想判斷一個列表是不是空的可以直接寫成if not my_list而不必寫if len(my_list) 0。再比如判斷用戶是否輸入了內(nèi)容username input(請輸入用戶名) if not username: print(用戶名不能為空) else: print(f歡迎你{username})當(dāng)用戶直接按下回車input返回的是空字符串空字符串被視為False所以not 為True程序就能正確提示“用戶名不能為空”。以下這些值在條件判斷中都會被視為FalseFalse0 和 0.0空字符串 空列表 []空元組 ()空字典 {}空集合 set()None利用這個特性可以讓代碼更簡潔但也要小心不要誤判。比如業(yè)務(wù)上希望“0是合法輸入”時就不能用if not value這種寫法來判斷用戶是否填了值因為0會被當(dāng)成False處理。8. 完整實戰(zhàn)把if知識串成一個帶菜單的臨時認(rèn)證系統(tǒng)8.1 需求設(shè)計與執(zhí)行流程梳理學(xué)了這么多語法知識點最后必須有一個綜合性的小項目把它們串起來。我設(shè)計一個很接近真實場景的小程序臨時員工門禁認(rèn)證系統(tǒng)。需求如下程序啟動后要求來訪者輸入姓名。姓名為空提示“姓名不能為空”并結(jié)束流程。姓名為“admin”直接提示“管理員身份歡迎進入后臺區(qū)域”。對普通來訪者繼續(xù)詢問訪問部門。如果訪問部門是“技術(shù)部”提示“訪客中有一位技術(shù)方向聯(lián)系人正在通知聯(lián)系人確認(rèn)請稍后”。如果訪問部門是“財務(wù)部”提示“財務(wù)部門需要提前預(yù)約請先到前臺登記”。其他部門提示“已經(jīng)記錄在案請聯(lián)系接待人員引導(dǎo)”。如果進入技術(shù)部的訪客還持有內(nèi)部工牌直接放行沒有工牌則需要暫停等待接待。這個程序涉及字符串輸入、空值判斷、多分支elif、嵌套判斷等多個知識點非常適合作為if語句的完整體檢。8.2 完整代碼實現(xiàn)與逐段解釋下面是完整代碼你可以直接復(fù)制到自己的Python環(huán)境里運行# 臨時員工門禁認(rèn)證系統(tǒng) name input(請輸入您的姓名) if not name: print(姓名不能為空請重新操作。) else: if name admin: print(管理員身份歡迎進入后臺區(qū)域。) else: print(f訪客{name}您好。) department input(請輸入您要訪問的部門) if department 技術(shù)部: print(您要訪問技術(shù)部正在通知技術(shù)部聯(lián)系人確認(rèn)。) has_badge input(請確認(rèn)是否持有內(nèi)部工牌是/否) if has_badge 是: print(工牌驗證通過放行。) elif has_badge 否: print(無工牌請在前臺領(lǐng)取臨時通行證后在閘機處進入。) else: print(輸入有誤請重新進行訪問登記。) elif department 財務(wù)部: print(財務(wù)部門需要提前預(yù)約請先到前臺登記。) else: print(已經(jīng)記錄在案請聯(lián)系接待人員引導(dǎo)進入。)這個程序比我前面寫的任何示例都更接近真實的業(yè)務(wù)代碼。它利用嵌套if處理“先判斷來訪者身份再判斷訪問部門最后判斷工牌情況”的三層邏輯。你可以自行多測幾組數(shù)據(jù)直接輸入admin、輸入普通姓名但部門留空、輸入財務(wù)部、輸入技術(shù)部且選是、選否、輸入其他。每一種輸入都會走到對應(yīng)分支只要有一處不符合預(yù)期你就能立刻感受到分支邏輯哪里還需要調(diào)整。8.3 用邊界值測試驗證程序的健壯性程序?qū)懲瓴粶y試等于白寫尤其是這種大量使用if的分支邏輯。建議你至少測試以下幾類“邊界情況”測試場景輸入內(nèi)容預(yù)期結(jié)果姓名為空直接回車提示姓名不能為空管理員身份admin提示進入后臺普通訪客技術(shù)部有工牌張三 / 技術(shù)部 / 是工牌驗證通過放行普通訪客技術(shù)部無工牌李四 / 技術(shù)部 / 否提示去前臺領(lǐng)臨時通行證普通訪客財務(wù)部王五 / 財務(wù)部提示需要預(yù)約普通訪客其他部門趙六 / 市場部聯(lián)系接待人員引導(dǎo)工牌輸入非“是/否”張三 / 技術(shù)部 / 隨便提示輸入有誤不要跳過這些測試。很多bug不是在正常路徑上暴露的而是在邊界值上。比如“輸入了空部門會怎樣”、“has_badge輸入了大小寫的‘是’會怎樣”這些都是邊界情況有助于你理解if條件覆蓋是否完整。9. 新手學(xué)if語句時最常出現(xiàn)的四個錯誤與排查思路9.1 少寫冒號條件行缺了個“”這是入門階段遇到報錯頻次最高的一個。if條件那一行末尾必須有英文冒號。漏掉的話Python會報SyntaxError: invalid syntax意思是語法錯誤。排查方法很簡單看到語法錯誤先檢查if那一行結(jié)尾是不是有冒號。記住不要用中文冒號Python只認(rèn)英文冒號。9.2 縮進混亂導(dǎo)致代碼不屬于它應(yīng)該屬于的分支縮進錯誤分成兩種一種是IndentationError代碼縮進不統(tǒng)一程序直接報錯另一種是代碼能運行但縮進的層級讓代碼執(zhí)行邏輯不對出現(xiàn)了隱藏bug。第一種容易發(fā)現(xiàn)第二種隱蔽得多。比如在if代碼塊里本來應(yīng)該和if平級的代碼不小心多縮進了幾個空格程序就會把它當(dāng)成if內(nèi)部的分支代碼來執(zhí)行導(dǎo)致邏輯完全變化。排查縮進問題最好的辦法是在編輯器里打開“顯示空格和Tab”的開關(guān)。VSCode中可以通過設(shè)置把空格顯示成小圓點這樣每個代碼行的縮進關(guān)系一目了然再也不會出現(xiàn)“看起來一樣、實際一個用空格一個用Tab”的情況。9.3 賦值符號混用把寫成這個錯前面提到過但因為它太典型必須再強調(diào)一次。if x 10這種寫法在Python中會直接報語法錯誤因為Python不允許在條件判斷中進行賦值操作。如果你真的想表達“x是否等于10”必須寫if x 10。我會在寫完條件判斷后心里默讀一遍“如果x等于10”而不會說“如果x是10”這樣能在潛意識里規(guī)避這個錯誤。9.4 類型錯位拿字符串跟數(shù)字硬比較input函數(shù)得到的結(jié)果永遠(yuǎn)是字符串。假如用戶輸入了18Python拿到的其實是“18”這個字符串。直接拿它和數(shù)字18比較大小Python 3會報TypeError: not supported between instances of str and int。正確做法是先做類型轉(zhuǎn)換age_input input(請輸入年齡) age int(age_input)但這個轉(zhuǎn)換也不是萬能的。如果用戶輸入的是“abc”或者“十八”int()又會拋ValueError。更健壯的寫法是配合try-except做異常捕獲不過那是后續(xù)的內(nèi)容現(xiàn)在你只需要記住“字符串不能直接和數(shù)字比較”這個規(guī)則即可。9.5 “語句看不懂”的拆解習(xí)慣先算條件值再看縮進塊很多初學(xué)者看到一行長得嚇人的if條件就蒙了比如if user is not None and user[age] 18 and user[level] in [gold, silver]:我的拆解方法是先把每個子條件單獨解出來標(biāo)出True或False再從左到右推導(dǎo)整體結(jié)果。拆解過程大致是user is not Noneuser不是空值假設(shè)為True。user[age] 18年齡字段大于等于18如果年齡是25就是True。user[level] in [gold, silver]等級在列表中如果等級是gold就是True。三個True用and連接最終結(jié)果是True。拆完之后代碼的邏輯就開始清晰了。讀懂一行長條件判斷的關(guān)鍵不是目測而是先拆成小塊逐一確認(rèn)真假再合成。這種習(xí)慣能讓你以后面對復(fù)雜條件時保持從容。10. 代碼可讀性的三個細(xì)節(jié)布爾變量、早退出與條件化簡10.1 用有意義的布爾變量給復(fù)雜條件命名復(fù)雜條件寫出來后雖然邏輯正確但可讀性很差。別人讀代碼時必須在腦子里把邏輯推導(dǎo)一遍才能理解。這時候可以引入布爾變量把條件“提煉”出來user {age: 25, level: gold} is_adult user[age] 18 is_vip user[level] in [gold, silver] if is_adult and is_vip: print(尊敬的成年會員歡迎參加相關(guān)活動。)is_adult和is_vip這兩個變量本身就帶有語義即便代碼再復(fù)雜閱讀者也能一眼看懂這段判斷是在檢查“是否成年”和“是否VIP”。這個習(xí)慣在工作后的代碼評審中非常重要推薦從學(xué)習(xí)階段就養(yǎng)成。10.2 提前結(jié)束的分支設(shè)計不要把所有邏輯塞進else里另外一種讓代碼更清晰的方式是提前退出guard clause具體表現(xiàn)就是識別到錯誤或異常情況時立刻終止當(dāng)前流程而不是把主流程放到層層else里面。對比一下兩種寫法不推薦value input(請輸入一個數(shù)字) if value: number int(value) if number 0: print(f{number} 是正數(shù)) else: print(輸入的不是正數(shù)) else: print(輸入不能為空)推薦value input(請輸入一個數(shù)字) if not value: print(輸入不能為空) else: number int(value) if number 0: print(f{number} 是正數(shù)) else: print(輸入的不是正數(shù))第二種寫法把異常情況放在前面直接處理異常情況一旦命中就不會再進入后續(xù)邏輯代碼層次會顯得更平直深入嵌套頁面時相對更容易理清。雖然這個例子里的優(yōu)勢還不明顯但遇到判定條件比較多、分支很深的場景這個習(xí)慣可以幫你保持腦子清醒。10.3 條件太復(fù)雜時抽函數(shù)是更好的解法如果一個條件長到連布爾變量都救不了比如邏輯上要同時判斷權(quán)限、時間、狀態(tài)、黑名單等多個維度這時候應(yīng)該考慮抽象成函數(shù)。等學(xué)到函數(shù)部分后你可以把“是否具備某種權(quán)限”變成一個專門的方法if條件里只調(diào)用它即可。這是后話但學(xué)習(xí)if時就可以有這種“封裝”意識。11. 我對if語句學(xué)習(xí)的幾個實際體會這次系統(tǒng)復(fù)習(xí)if語句比第一次零散學(xué)習(xí)時確實通透了很多。有幾個自己的實際體會寫在這里供參考。第一if語法本身一天就能學(xué)完但分支邏輯的鍛煉需要大量做小題目。不要滿足于看懂代碼多拿紙筆把一個程序的執(zhí)行分支手推一遍當(dāng)你能完全不靠運行就說出任意輸入的輸出時才算真正掌握了這一段邏輯。第二學(xué)習(xí)時盡量用小例子驗證單個知識點不要一上來就背一堆規(guī)則。比如想知道and和or的優(yōu)先級你就寫兩三個小print試驗一下想知道in對字符串的判斷是否區(qū)分大小寫也寫個小例子跑一遍。自己驗證出來的記憶比死記硬背牢固得多。第三不要怕報錯。寫if語句時報錯信息反而是你最好的老師。幾乎每一條報錯都在告訴你精確的行號和原因SyntaxError是語法寫錯了IndentationError是縮進位錯了TypeError是類型不匹配。每次報錯后花一點時間讀懂報錯英文進步會非???。第四實際寫程序時if語句極少單獨出現(xiàn)它總是和循環(huán)、函數(shù)、類綁定在一起。學(xué)習(xí)初期先把基礎(chǔ)分支結(jié)構(gòu)練扎實后面學(xué)到while循環(huán)和for循環(huán)后你會發(fā)現(xiàn)條件和循環(huán)疊加在一起才是真正解決復(fù)雜問題的開始。if是基座這個基座打得穩(wěn)后面的大樓才不會歪。