python程序設計 課件 第3章 賦值與條件_第1頁
python程序設計 課件 第3章 賦值與條件_第2頁
python程序設計 課件 第3章 賦值與條件_第3頁
python程序設計 課件 第3章 賦值與條件_第4頁
python程序設計 課件 第3章 賦值與條件_第5頁
已閱讀5頁,還剩108頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第3章賦值語句與分支結構Python程序設計第3章賦值語句與分支結構簡單的程序一般遵循輸入、處理、輸出(IPO)模式。整個Python程序由許多模塊組成,模塊里含有程序語句,語句各有其意義并含有表達式,表達式則建立并操作對象。有了基本的構建塊(標識符和表達式),就可以更完整地描述各種Python語句。一些編程語言提供了異常處理機制,讓程序更具“防御性”。Python的異常處理機制是try-except語句。初識語句1分支語句4賦值語句2input賦值語句3pass語句6目錄異常處理機制53.1初識語句語句基本概念表達式語句特有的縮進3.1

初識語句語句是Python程序里最小最基本的執行單位,每種語句都有其獨特的語法和語義。不符合語句的語法,就不是合法的程序代碼,也就不能被解釋器正確解析并執行。而學習編寫Python程序,也就是學習各種語句所代表的意思,再加上表達式,表達出你想要的程序行為。3.1.1語句基本概念Python語句可分為簡單語句與復合語句,大致上可以這么認為:能寫成一行程序代碼的是簡單語句,跨越好幾行的是復合語句。某些簡單語句可以跨好幾行,但事實上Python解釋器會把它們當作同一行看待;有時復合語句的程序碼太短了,因此Python語法也允許寫在同一行上。表3-1了列出Python的所有語句。3.1.1語句基本概念表3-1語句一覽表3.1.2表達式語句任何表達式同時也都是合法的語句,所以“3”、“3+5”、“3<5”、“x<yorz<x”等等,它們既是表達式也是語句,因此我們可以在Python解釋器的互動模式里輸入“3”并執行。Python程序可使用分號“;”標示語句的結尾,但也可以不寫;但若使用分號,便可把多個語句寫在同一行上。實際開發中很少把多個語句寫在同一行上,因為這樣會導致程序的可讀性差。>>>1+2 #表達式也是合法語句3>>>1+2; #以分號“;”標示語句結尾3>>>1+2;3+4;5+6; #以分號“;”隔開語句37113.1.2表達式語句3.1.3特有的縮進Python使用縮排來標示程序代碼的層級,所以語法非常簡潔,不同于C/C++/Java/C#/JavaScript以大括號“{}”包住一堆程序代碼的方式。不過第一次接觸縮排格式的人會很不習慣,有道是:“若能搞懂縮排,就已經搞懂Python語法的一半了”。Python語法規定,縮排可以是四個空格(建議)、兩個空格、一個TAB鍵或任何其他組合,重點在于保持一致、不要混用。本書的程序中一律采用四個空格的方式。3.2

賦值語句基本賦值語句多重賦值語句同時賦值語句增強賦值語句3.2

賦值語句Python中使用等號(=)表示將值賦給變量。利用賦值,程序可以從鍵盤獲得輸入。Python還允許同時賦值,這對于利用單個提示獲取多個輸入值很有用處。賦值語句是Python中重要的語句之一,務必完整且清楚地了解賦值語句。3.2.1基本賦值語句基本賦值語句具有以下形式:<標識符>=<表達式>執行賦值語句時,解釋器先執行等號右邊的表達式,得到結果(對象)后,再賦值給等號左邊的名稱,將該值與左側命名的變量相關聯,建立起名稱與對象之間的關系,我們其為“綁定”。例如:>>>a=3 #建立int對象值為3,產生名稱a(第一次),賦值>>>b=3+5 #運算結果是整數對象8,取名為b>>>c=a<b #運算結果是bool對象,值為True,c指向此對象>>>a=a+1 #運算結果是個新對象,a轉而指向該對象3.2.1基本賦值語句賦值語句左邊的名稱第一次出現時,Python解釋器便會建立此名稱。該名稱可以多次被賦值,但它只保留最新賦的值。后面出現的賦值會使該名稱轉而指向別的對象,也就是建立新的綁定關系。所以,在上述程序代碼里,“a=3”是第一次建立a,解釋器會產生該名稱并指向int對象3;之后執行“a=a+1”時,先運算右邊,得到新的int對象4,然后讓a轉而指向該對象,這個語句展示了如何使用名稱的當前值來更新它的值。名稱的值可以改變,這就是為什么它們被稱為“變量”的原因。我們可以將“變量”看作是計算機內存中的一種命名的存儲位置,可以在其中放入一個值。當變量更改時,舊值被刪除并寫入一個新值。3.2.1基本賦值語句如果一個值不再被任何名稱所引用,它就不再有用。Python將自動從內存中清除這些值,以便收回存儲空間。現在,大家應該很清楚“名稱”、“變量”、“對象”和“類型”的關系了。但有時候我們會以不同的說法描述,當我們說:·“對象a”時,正確說法是“名稱a指向的那個對象”;·“對象a是個int”時,正確說法是“名稱a指向的對象,類型是int”;·“浮點數3.14”時,正確說法是“有個類型為?oat的對象,其值為3.14”;·“3是個整數對象”時,正確說法是“執行程序代碼3后會建立類型為int的對象,其值為3”;·“整數對象a為3”時,正確說法是“名稱a指向類型int的對象,其值為3”;3.2.1基本賦值語句·“字符串s”時,正確說法是“名稱s指向的對象,其類型是str”;·“tuple類型不可變”時,正確說法是“類型tuple的對象一旦建立,其內容就不會改變”;·“list對象li”時,正確說法是“名稱li指向類型為list的對象”;·“list是可變對象”時,正確說法是“類型為list的對象是可變的”;·“t是個tuple”時,正確說法是“名稱t指向類型為tuple的對象”。3.2.2多重賦值語句所謂多重賦值,是指在同一行內,讓同一個對象賦值(綁定)到多個名稱,以及用分號“;”隔開多個賦值語句。在使用多重賦值時,要當心可變對象與不可變對象的差別。上述程序代碼中,因為int對象3不可變,所以透過名稱a、b與c無法修改所指向的int對象3。若是可變的list對象,則透過y修改該對象的話,那么x指向的對象也變了,因為x與y指向的對象是同一個。(想一想?)>>>a=b=c=3 #a、b、c都指向同一個int對象3>>>b=4;c=5 #以分號隔開兩個語句,重新賦值b與c>>>a3>>>x=y=z=[0,1,2]#都指向同一個list對象>>>y[0]=99 #list是可變對象,修改>>>z=[30,41,52] #名稱z轉而指向新對象>>>x,y,z #x與y指向同一個對象([99,1,2],[99,1,2],[30,41,52])3.2.2多重賦值語句3.2.3同時賦值語句若想把多個對象在同一行內賦值給多個名稱,可使用“同時賦值”(又稱“序列賦值”),即一個賦值語句允許同時計算幾個值。它看起來像這樣: <名稱1>,<名稱2>,...,<名稱n>=<表達式1>,<表達式2>,...,<表達式n>它告訴Python對右側所有表達式求值,然后將這些值賦給左側命名的相應名稱。例如: sum,diff=x+y,x-y這里,sum得到x和y的和,diff得到x和y的差。3.2.3同時賦值語句這種形式的賦值實際上非常有用。例如:假設有兩個變量x和y,你希望交換它們的值。也就是說,你希望將當前存儲在x中的值存儲在y中,將當前存儲在y中的值存儲在x中。下面這樣做是不行的: x=y y=x因為最終得到了原始y值的兩個副本(想一想為什么?)。3.2.3同時賦值語句完成交換的一種方法是引入一個附加變量,它暫時記住x的原始值。 temp=x x=y y=temp這種三變量交換的方式在其他編程語言中很常見。在Python中,同時賦值語句提供了一種優雅的選擇。下面是簡單的Python等價寫法,因為賦值是同時的: x,y=y,x又例如:>>>(a,b,c)=(0,1,2) #左邊是tuple(元組,不可變的列表)>>>a,b,c=0,1,2 #tuple可省略括號>>>a,b=b,a #交換a與b所指向的對象>>>a,b #a,b原來是(0,1)(1,0) #現在是(1,0)>>>x=[0,1];i=0>>>i,x[i]=1,2 #注意i先成為1,然后才賦值x[i]>>>x[0,2] #所以是x[1]變了3.2.3同時賦值語句3.2.3同時賦值語句不僅可以使用元組(tuple),也可以使用方括號(list);使用這種賦值語句時,等號右邊可以是任何序列類型,例如list、tuple、str等。 >>>a,b,c=[0,1,2] #等號右邊可以是list對象 >>>[a,b,c]=[0,1,2] #等號左邊也可以使用方括號 >>>a,b,c='abc' #等號右邊可以是str對象 >>>a,b,c #查看,a、b、c分別指向一個str對象 ('a','b','c') #每個str對象只含一個字元 >>>data=['John',165,51,('C','Python’)] >>>name,height,weight,(lang0,lang1)=data >>>name,height,weight,lang0,lang1 ('John',165,51,'C','Python')3.2.3同時賦值語句“序列賦值”最好用的情況是當你知道某容器對象的內部結構時,可以迅速地把其內容抽取出來,例如上面的data。使用此種賦值能減少程序代碼行數,但實際開發時,應把相關的數據放在一起、不相關的分開,這樣才能讓程序代碼易讀易懂。上面的序列賦值,語句左右兩邊的個數必須相同,否則會發生錯誤。此外,“星號序列賦值”適合用于長度不定或未知的情況。例如:>>>x=[0,1,2,3,4]>>>a,*b,c=x #星號,其余元素通通都會放進b>>>a,b,c(0,[1,2,3],4)#b是個列表對象>>>head,*rest=x #拿出x列表里的第0個元素>>>head,rest #剩余的通通放進rest(0,[1,2,3,4])>>>*rest,t1,t0=x #拿出倒數兩個元素>>>rest,t1,t0 #剩余的通通放進rest([0,1,2],3,4)3.2.3同時賦值語句>>>a0,a1,a2,a3,*a4=x#注意,當兩邊個數相等時,>>>a0,a1,a2,a3,a4#以星號標示的名稱a4,(0,1,2,3,[4]) #仍然會是list對象>>>a0,a1,a2,a3,*a4,a5=x>>>a0,a1,a2,a3,a4,a5#當左邊名稱個數多于右邊時,(0,1,2,3,[],4) #以星號標示的名稱會指向空列表,3.2.3同時賦值語句>>>a0,*a1,*a2,a3=x#此種形式的兩個星號,發生錯誤

File"<stdin>",line1a0,*a1,*a2,a3^SyntaxError:invalidsyntax#語法錯誤:無效語法>>>record=('John',50,123.45,(12,18,2012))>>>name,*_,(*_,year)=record #這種形式的兩個星號,合法想要的才取名稱,>>>name,year#不需要的東西就隨便給個名稱,例如下劃線“_”('John',2012)3.2.3同時賦值語句3.2.4增強賦值語句增強賦值語句是指運算符中有“+=、-=、*=、/=、//=、%=、**=、>>=、<<=、&=、^=、|=”。以“x+=y”為例,其語義“幾乎”等同于“x=x+y”,實際行為必須視語句左邊的對象是否為可變對象而定。例如:>>>a=b=3>>>a+=8 #等同于a=a+8>>>(a,b) #因為int對象不可變(11,3) #a、b指向不同的對象>>>x=y=[0,1,2] #x與y指向同一個可變對象>>>x+=[98,99] #注意:這會改變x指向的對象>>>x,y([0,1,2,98,99],[0,1,2,98,99])>>>xisy #x跟y是同一個對象True3.2.4增強賦值語句>>>x=y=[0,1,2] #讓我們再試一次,>>>x=x+[98,99] #這次使用表達式x+[98,99]>>>x,y #名稱x會轉而指向運算后的新對象([0,1,2,98,99],[0,1,2])>>>xisy #x與y不是同一個對象False3.2.4增強賦值語句3.2.4增強賦值語句執行“x+=y”時,若x是不可變對象,那么其行為等同于“x=x+y”;但若x是可變對象,那么“x+=y”將會修改x對象而不是產生新對象,這種行為叫做“原地修改”;而“x=x+[98,99]”則是由表達式“x+[98,99]”產生新的對象,再指派給名稱x。請仔細琢磨這一段的含義。3.3

input賦值語句3.3

input賦值語句輸入語句的目的是從程序的用戶那里獲取信息并存儲到變量中。在Python中,輸入是用一個賦值語句結合一個內置函數input實現的。輸入語句的具體形式,取決于你希望從用戶那里獲取的數據類型。對于文本輸入,語句如下所示: <變量>=input(<字符串表達式>)這里的<字符串表達式>用于提示用戶輸入,該提示幾乎總是一個字符串字面量(即引號內的一些文本)。3.3

input賦值語句當Python遇到對input的調用時,它在屏幕上打印提示。然后,暫停并等待用戶鍵入一些文本,鍵入完成后按回車鍵。用戶輸入的任何東西都會存儲為字符串,例如: >>>name=input("請輸入你的名字:")請輸入你的名字:xiaoming >>>name 'xiaoming'執行input語句時Python打印輸出提示“請輸入你的名字:”,然后解釋器暫停,等待用戶輸入。在這個例子中鍵入xiaoming(小明),結果字符串“xiaoming”被記在名稱name中。對name求值將返回鍵入的字符串。3.3

input賦值語句如果希望接收的是用戶輸入的一個數字,就需要形式稍復雜一點的input語句: <變量>=eval(input(<字符串表達式>))這里添加了另一個Python的內置函數eval,它內嵌了input函數。eval是“evaluate(求值)”的縮寫。在這種形式中,用戶鍵入的文本被求值為一個表達式,以產生存儲到變量中的值。例如字符串“32”被轉換成數字32: x=eval(input("請輸入0到1之間的數字:")) celsius=eval(input("攝氏溫度是多少?"))應該在提示結尾處的引號內安排一個空格,以使用戶輸入的內容不會緊挨著提示開始,讓交互更容易閱讀和理解。3.3

input賦值語句雖然數字示例特別提示用戶輸入數字,但實際上用戶鍵入的只是一個數字字面量,即一個簡單的Python表達式。事實上,任何有效的表達式都是可接受的。請考慮下面與Python解釋器的交互: >>>ans=eval(input("請輸入一個表達式:"))請輸入一個表達式:3+4*5 >>>print(ans) 23 >>>這里,提示輸入表達式時,用戶鍵入“3+4*5”,Python通過eval對此表達式求值,并將值賦給變量ans。打印時,我們看到ans的值為23,與預期一樣。不同的是,用戶在語句執行時提供的是表達式。3.3

input賦值語句eval函數功能很強大,但也有“潛在的危險”。如本例所示,當我們對用戶輸入求值時,本質上是允許用戶輸入一部分程序。Python將盡職盡責地對他們輸入的任何內容求值,了解Python的人就有可能利用這種能力輸入惡意指令。例如,用戶可以鍵入記錄計算機上的私人信息或刪除文件的表達式。在計算機安全中,這被稱為“代碼注入”攻擊,因為攻擊者將惡意代碼注入正在運行的程序中。【程序實例3-1】用單個input從用戶那里獲取多個數字,求出考試平均分。#avg.py#計算兩個考試分數的平均值的簡單程序,用來說明多個輸入的使用。defmain():print("這個程序計算兩個考試分數的平均值。")score1,score2=eva1(input("輸入以逗號分隔的兩個分數:"))average=(score1+score2)/2print("分數的平均值是:",average)main()請記錄:上面代碼的運行結果_________________________________________________3.3

input賦值語句3.3

input賦值語句該程序提示用逗號分隔兩個分數,例如input語句的效果就像進行以下賦值: score1,score2=86,92這個例子可以擴展到任意數量的輸入。當然,也可以通過單獨的input語句獲得用戶的輸入: score1=eval(input("輸入第一個分數:")) score2=eval(input("輸入第二個分數:"))某種程度上,這可能更好,因為單獨的提示對用戶來說信息更準確。有時在單個input中獲取多個值提供了更直觀的用戶接口。但要記住,多個值的技巧不適用于字符串(非求值)輸入,如果用戶鍵入逗號,它只是輸入字符串中的一個字符。3.4

分支語句簡單分支語句復雜分支語句多重條件分支語句程序示例:尋找三個數中最大的一個3.4

分支語句計算機程序是指令的序列,序列是編程的一個基本概念。但是,只用序列不足以解決所有問題,實踐中常常需要改變程序的順序流程,以適應特定情況的需要。這是通過稱為“控制結構”的特殊語句來完成的。“判斷”是允許程序針對不同情況執行不同指令序列的控制結構,實際上允許程序“選擇”適當的動作過程。條件語句根據表達式的運算結果(True或False)來判斷應該執行哪部分的程序代碼(分支),控制程序走向,我們稱呼此類的語句為程序流控制。3.4

分支語句在Python中,簡單的判斷用一個if語句來實現,兩路判斷通常使用if-else,多路判斷用if-elif-else實現。如果判斷結構是嵌套的,則結合判斷的算法可能會變得相當復雜。在程序設計過程中,通常有許多解決方案可選,程序員應仔細考慮,得到正確、有效和可理解的程序。判斷基于條件的求值,條件是簡單的布爾表達式,其運算結果為True或False。Python有專門的布爾數據類型,其字面量為True和False。條件的構成利用了關系運算符<、<=、!=、==、>和>=。3.4

分支語句if語句的一般形式如下,其中elif與else為可選項,elif也可以有好幾個:if表達式:

語句語句...elif表達式:

語句語句...else:

語句語句...3.4

分支語句if、elif、else那一行的最后面必須加上冒號“:“,代表后面接著一組程序語句,而里面的語句必須縮排。在上面的程序代碼里,因為表達式“a<b”為真,所以會進入if內的程序代碼,若“a<b”的結果為假,就會跳過不執行。當輸入“ifa<b:”時,若解釋器處于互動模式,會輸出“...”提醒你這不是有效語句,無法執行,要求你繼續輸入,而在冒號“:”之下的程序代碼必須縮排。“ifa<b:”之后的程序代碼可含有多個語句(此例中只有一個),然后直接按回車鍵輸入空行,代表結束;在解釋器互動模式下才須如此,若是寫在文件中就不需要了。例如:>>>a=3 #a之前沒有空格>>>a=3 #a之前有一個空格,發生錯誤

File"<stdin>",line1a=3^IndentationError:unexpectedindent#縮排錯誤:未預期縮排>>>a,b,x=3,5,-1>>>ifa<b: #如果a小于b...x=a #讓x指向對象a;在x之前輸入四個空格... #直接按回車鍵輸入空行,代表結束if語句>>>x #x指向333.4

分支語句3.4.1簡單分支語句我們簡單判斷開始。作為一個例子,先回顧一下攝氏溫度轉換為華氏溫度的程序(參見程序實例2-1)。我們來加強這個程序,以確保在溫度極端(相當熱或相當冷)時程序能打印出適當的警告提示。3.4.1簡單分支語句第一步是給出完整的增強規格說明。假設當溫度超過90華氏度時應該發出熱警告,而低于30華氏度時則會發出冷警告。為此,設計一個擴展的算法如下:以攝氏度輸入溫度值計算華氏溫度為9/5攝氏度+32輸出華氏度值如果華氏度>90

打印熱警告如果華氏度<30

打印冷警告這個設計在結束時有兩個簡單的“判斷”。縮進表示只有滿足上一行中列出的條件才執行該步驟。判斷引入了一個替代的控制流,算法采取的步驟取決于華氏度的值。3.4.1簡單分支語句如圖是一個流程圖,展示算法可能采取的路徑。菱形框表示有條件的判斷。如果條件為假,則控制傳遞到序列中的下一個語句;如果條件成立,則控制權轉移到右側框中的指令,這些指令完成后,控制會傳遞到下一個語句。

帶有警告的溫度轉換程序流程圖【程序實例3-2】帶溫度警告的攝氏溫度轉換為華氏溫度的Python程序。#convert2.py#將攝氏溫度轉換為華氏溫度的程序。此版本發出熱和冷警告defmain():celsius=float(input("攝氏溫度是多少?"))fahrenheit=9/5*celsius+32print("溫度是",fahrenheit,"華氏度。")#打印極端溫度警告

iffahrenheit>90:print("那里真的很熱。小心!")iffahrenheit<30:print("特別提醒,一定要穿得暖和些!")main()3.4.1簡單分支語句3.4.1簡單分支語句可以看到,Python的if語句用于實現判斷。if<條件>:<序列>這里<序列>是if頭部下縮進的一個或多個語句的序列。在convert2.py中有兩個if語句,每個<序列>中都有一個語句。可見,if的語義是:首先,對頭部中的條件求值。如果條件為真,則執行<序列>中的語句,然后控制傳遞到程序中的下一條語句;如果條件為假,則跳過<序列>中的語句。If的<序列>是否執行取決于條件,不論哪種情況,控制隨后會傳遞到if后的下一個語句,這是“一路”判斷或“簡單”判斷。簡單if語句的控制流3.4.1簡單分支語句2.形成簡單條件上述程序使用的簡單條件比較兩個表達式的值:<expr><relop><expr>。<relop>是“關系運算符”的縮寫,是“小于”或“等于”這類數學概念的特別名稱。Python中有6個關系運算符。表3-2Python中的關系運算符3.4.1簡單分支語句特別要注意用“==”表示相等。由于Python已經使用“=”符號來表示賦值語句,因此對于相等概念,需要使用不同的符號。條件可以用于比較數字或字符串。比較字符串時,排序是根據底層的Unicode值以字母順序放置的字符串。因此,所有大寫拉丁字母都在小寫字母之前(例如,“Bbbb”在“aaaa”之前,因為“B”在“a”之前)。條件實際上是一種布爾表達式,對它求值會產生值True(條件成立)或False(條件不成立)。某些語言(如C++)用整數1和0來表示這些值。在Python中,布爾表達式類型為bool,布爾值true和false由字面量True和False表示。下面是一些交互示例: >>>3<4 True >>>3*4<3+4 False >>>"hello"=="hello" True >>>"hello"<"hello" False >>>"Hello"<"hello" True3.4.1簡單分支語句3.4.1簡單分支語句3.條件程序執行運行Python程序有幾種不同的方式。一些Python模塊文件被設計為直接運行,這些通常被稱為“程序”或“腳本”。其他Python模塊主要設計為讓其他程序導入和使用,這些通常被稱為“庫”。有時我們希望創建一種混合模塊,它既可以作為獨立程序使用,也可以作為由其他程序導入的庫使用。到目前為止,我們編寫的大多數程序在底部有一行main()來調用main函數,啟動該程序的運行,這些程序適合直接運行。在窗口環境中,可以通過點擊(或雙擊)圖標來運行該文件,或者鍵入類似Python<myfile>這樣的命令。3.4.1簡單分支語句由于Python在導入過程中對模塊中的行求值,所以當前程序在導入到交互式Python會話或另一個Python程序時也會運行。一般來說,不要讓模塊在導入時運行。以交互方式測試程序時,通常的方法是首先導入模塊,然后在每次運行時調用它的main(或一些其他函數)。如果程序設計為既可以導入(不運行)又可以直接運行,則對底部的main的調用必須是有條件的。一個簡單的判斷應該就能搞定,我們只需要找到合適的條件: if<條件>: main()無論何時導入模塊,Python都會在該模塊內部創建一個特殊的變量__name__,并為其分配一個表示模塊名稱的字符串。3.4.1簡單分支語句下面是一個示例交互,顯示math庫的情況: >>>importmath >>>math.__name__ 'math'可以看到,在導入后,math模塊中的__name__變量賦為字符串“math”。但是,如果直接運行Python代碼(不導入),Python會將__name__的值設置為 “__main__”。 >>>__name__ '__main__'3.4.1簡單分支語句例如,我們可以改變程序的最后一行,像這樣: if__name__=='__main__’: main()這保證在直接調用程序時自動運行main,但如果導入模塊,就不會運行。幾乎在每個Python程序的底部,都會看到類似這樣的一行代碼。3.4.2復雜分支語句if語句還可以加上elif與else做更復雜的條件判斷。我們稱elif與else為子句,它們不可獨立存在,屬于if語句的一部分。>>>t=999;x=None #以None代表無效值>>>ift<0: #如果if為真...x=-1 #執行此處...elif0<=tandt<=100: #如果if為假而這里為真...x=t #執行此處...else: #如果之前皆為假...x=101 #執行此處... #以此例而言,最后x會是101...elif #若只輸入elif或elseFile"<stdin>",line1elif^SyntaxError:invalidsyntax#語法錯誤:無效語法3.4.2復雜分支語句3.4.2復雜分支語句執行if/elif/elif.../else組成的語句時,會從上到下逐一判斷if與elif的表達式是否為真,若為真便執行對應的程序代碼,然后跳到語句組之后繼續執行;若所有的if與elif皆為假,便會執行else子句(如果有的話)的程序代碼。3.4.2復雜分支語句if語句內部還可以有if語句,形成嵌套結構,例如,下面的操作是找出a、b、c三個數中最大的一個:>>>a,b,c=3,5,7;x=None>>>ifa<b: #縮排零層...ifb<c: #縮排一層...x=c #縮排二層...else: #縮排一層...x=b #縮排二層...else: #縮排零層...ifa<c: #縮排一層3.4.2復雜分支語句...x=c #縮排二層...else: #縮排一層...x=a #縮排二層... #最后x會是a、b、c中最大的...ifa<b #忘記冒號“:”File"<stdin>",line1ifa<b^SyntaxError:invalidsyntax#語法錯誤:無效語法在if語句中嵌套if語句時,必須再多縮排一層,這樣Python解釋器才能看懂程序代碼。【程序實例3-3】二次方程求解程序。#quadratic.py#計算二次方程實根的程序,說明數學庫的使用#如果方程沒有真正的根,該程序會崩潰importmath #使數學庫可用defmain():print("該程序找到二次方程的真實解。")print()a=float(input("輸入系數a:"))3.4.2復雜分支語句b=float(input("輸入系數b:"))c=float(input("輸入系數c:"))discRoot=math.sqrt(b*b-4*a*c)root1=(-b+discRoot)/(2*a)root2=(-b-discRoot)/(2*a)print()print("這組解是:",root1,root2)main()3.4.2復雜分支語句3.4.2復雜分支語句程序注釋中指出,如果給出的系數造成沒有實根的二次方程時,該程序會崩潰。這段代碼的問題是當b2-4ac小于0時,程序試圖取負數的平方根。由于負數沒有實根,所以程序報告錯誤。請看下面這個執行的這個例子: >>>main()該程序找到二次方程的真實解。3.4.2復雜分支語句輸入系數a:1輸入系數b:2輸入系數c:3Traceback(mostrecentcalllast):File"quadratic.py",line23,in<module>main()File"quadratic.py",line16,inmaindiscRoot=math.sqrt(b*b–4*a*c)ValueError:mathdomainerror【程序實例3-4】二次方程求解程序,增加一個判斷以保證程序不會崩潰。#quadratic2.pyimportmathdefmain():print("該程序找到二次方程的真實解。\n")a=float(input("輸入系數a:"))b=float(input("輸入系數b:"))c=float(input("輸入系數c:"))3.4.2復雜分支語句discrim=b*b-4*a*cifdiscrim>=0:discRoot=math.sqrt(discrim)root1=(-b+discRoot)/(2*a)root2=(-b-discRoot)/(2*a)print("\n這組解是:",root1,root2)main()3.4.2復雜分支語句3.4.2復雜分支語句這個修改版本首先計算判別式(b2-4ac)的值,再檢查并確保它不是負數。然后程序繼續取平方根并計算解。如果dscrim為負數,該程序將不會調用math.sqrt。下面是交互執行的示例:>>>main()該程序找到二次方程的真實解。輸入系數a:1輸入系數b:2輸入系數c:3>>>3.4.2復雜分支語句當方程沒有實根時,即當b*b–4*a*c小于零時,程序將簡單地跳過計算并轉到下一條語句。由于沒有下一條語句,程序就會退出。不過,這幾乎比以前的版本更差,因為它不給用戶任何跡象表明發生什么錯誤,只是讓程序中止。好的程序應該打印一條消息,告訴用戶他們指定的方程沒有實數解。我們可以通過在程序結束時添加另一個簡單的判斷來實現這一點。 ifdiscrim<0: print("這個等式沒有實數解!")但這個解決方案還有問題。程序中有兩個條件但只有一個判斷。根據dscrim的值,程序應該打印沒有實數根,或者計算并顯示根。這是一個兩路判斷的例子。3.4.2復雜分支語句在Python中,可以通過if-else語句,即在if子句后加上else子句來實現兩路判斷。if<條件>:<陳述>else:<陳述>當Python解釋器遇到這種結構時,它首先對條件求值。如果條件為真,則執行if下的語句;如果條件為假,則執行else下的語句。在任何情況下,控制隨后都轉到if-else之后的語句。【程序實例3-5】二次方程求解程序,使用兩路判斷,得到一個更好的解決方案。#quadratic3.pyimportmathdefmain():print("該程序找到二次方程的真實解。\n")a=float(input("輸入系數a:"))b=float(input("輸入系數b:"))c=float(input("輸入系數c:"))3.4.2復雜分支語句discrim=b*b-4*a*cifdiscrim<0:print("\n這個等式沒有實根!")else:discRoot=math.sqrt(b*b-4*a*c)root1=(-b+discRoot)/(2*a)root2=(-b-discRoot)/(2*a)print("\n這組解是:",root1,root2)main()3.4.2復雜分支語句3.4.2復雜分支語句下面是兩次運行這個程序的示例會話:>>>main()該程序找到二次方程的真實解。輸入系數a:1輸入系數b:2輸入系數c:3這個等式沒有實根!3.4.2復雜分支語句>>>main()該程序找到二次方程的真實解。輸入系數a:2輸入系數b:4輸入系數c:1這組解是:-0.2928932188134524-1.7071067811865475>>>3.4.3多重條件分支語句程序示例3-5所示的二次方程求解程序改進較大,但是還存在一些問題。例如:>>>main()該程序找到二次方程的真實解。輸入系數a:1輸入系數b:2輸入系數c:1這組解是:-1.0-1.0這在技術上是正確的,給定的系數產生一個方程,有相等的根為-1。但是,輸出可能會使某些用戶感到困惑。程序應該給出更多信息,以避免混亂。3.4.3多重條件分支語句當discrim為0時,發生等根的情況。在這種情況下,discRoot也為0,并且兩個根的值為-b。如果希望捕捉這種特殊情況,程序實際上需要一個三路判斷,即:…檢查discrim的值當<0:處理沒有根的情況當=0:處理雙根的情況當>0:處理兩個不同根的情況。該算法的一種編碼方法是用兩個if-else語句。if或else子句的主體可以包含任何合法的Python語句,包括其他if或if-else語句。將一個復合語句放入另一個復合語句稱為“嵌套”。3.4.3多重條件分支語句下面是用嵌套來實現三路判斷的代碼片段:ifdiscrim<0:print("沒有實根!")else:ifdiscrim==0:root=-b/(2*a)print("有一個雙根",root)else:#有兩個不同的根3.4.3多重條件分支語句仔細觀察這段代碼,會看到有三種可能的路徑。代碼序列由dscrim的值確定。該解決方案的流程圖如圖所示。你可以看到頂層結構只是一個if-else(將虛線框視為一個大語句)。虛線框包含第二個if-else,嵌套在頂級判斷的else部分中。

使用嵌套if-else的二次求解器的三路判斷3.4.3多重條件分支語句這個解決方案雖然有效,但是用兩個兩路判斷實現的三路判斷,得到的代碼不反映原始問題的真正三路判斷思維。設想一下,如果我們需要像這樣做一個五路判斷呢。這個時候if-else結構將嵌套四層,Python代碼會一直寫到屏幕的右邊。(資深程序員會告訴你,其實所編寫的程序也是“苗條”的好,因為“胖”了,說明程序嵌套深,這樣的程序就復雜了。)3.4.3多重條件分支語句在Python中編寫多路判斷還有另一種方法,它保留了嵌套結構的語義,但看起來更舒服。這就是將一個else和一個if組合成一個稱為elif的子句(讀作“ell-if”)。if<條件1>:<情況1陳述>elif<條件2>:<情況2陳述>elif<條件3>:<情況3陳述>…else:<缺省陳述>3.4.3多重條件分支語句這個格式用于分隔任意數量的互斥代碼塊。Python將依次對每個條件求值,尋找第一個為真的條件。如果找到真條件,就執行在該條件下縮進的語句,并且控制轉到整個if-elif-else之后的下一語句。如果沒有條件為真,則執行else下的語句。else子句是可選的,如果省略,則可能沒有語句塊被執行。【程序實例3-6】二次方程求解程序,用if-elif-else表示三路判斷得到很好的程序。#quadratic4.pyimportmathdefmain():print("該程序找到二次方程的真實解。\n")a=float(input("輸入系數a:"))b=float(input("輸入系數b:"))c=float(input("輸入系數c:"))discrim=b*b-4*a*c3.4.3多重條件分支語句ifdiscrim<0:print("\n這個等式沒有實根!")elifdiscrim==0:root=-b/(2*a)print("\n有一個雙根!",root)else:discRoot=math.sqrt(b*b-4*a*c)root1=(-b+discRoot)/(2*a)root2=(-b-discRoot)/(2*a)print("\n這組解是:",root1,root2)main()3.4.3多重條件分支語句3.4.4程序示例:尋找三個數中最大的一個由于判斷結構可以改變程序的控制流,因此算法就從單調、逐步、嚴格的順序處理中解脫了出來。下面,我們來看一個更復雜的判斷問題設計,從而展示設計過程中的一些挑戰。假設我們需要一個算法,找出三個數中最大的一個。這個算法可能是一個更大的問題的一部分,例如確定等級或計算稅額。也就是說,計算機如何確定用戶的三個輸入中哪一個最大?下面是簡單的程序大綱:defmain():x1,x2,x3=eval(input("請輸入三個值:"))#填補代碼將maxval設置為最大值

print("最大的值是",maxval)3.4.4程序示例:尋找三個數中最大的一個請注意,這里使用eval來獲取三個數,這種方式比較“粗暴”。在程序設計實踐中,通常應該避免eval。不過,這里我們只是關心開發和測試一些算法思想。在閱讀下面的分析之前,建議你先試著自己解決這個問題。3.4.4程序示例:尋找三個數中最大的一個1.策略1:比較每個值顯然,這個程序向我們提出了一個判斷問題。我們需要一系列語句,將maxval的值設置為三個輸入x1、x2和x3中的最大值。看上去這像是一個三路判斷。maxval=x1maxval=x2maxval=x33.4.4程序示例:尋找三個數中最大的一個讓我們考慮第一種可能性:x1最大。為了確定x1確實是最大的,我們只需要檢查它至少與另外兩個一樣大。下面是第一次嘗試:ifx1>=x2>=x3:maxval=x1Python允許這種復合條件,也就是說,當x1至少與x2一樣大且x2至少與x3一樣大時,條件為真。條件清楚地表明x1至少與x2和x3一樣大,因此將其值賦給maxval應該是正確的(始終要特別注意邊界值)。但是,我們是否能確定當x1最大時,在所有情況下這個條件都是真的呢?假設實際值是5、2和4,顯然,x1是最大的,但條件返回false,因為關系5≥2≥4不成立。3.4.4程序示例:尋找三個數中最大的一個要確保x1是最大的,但不關心x2和x3的相對順序。我們真正需要的是確定x1>=x2且x1>=x3。Python允許我們測試這樣的多個條件,只要用and關鍵字將它們組合起來:ifx1>=x2andx1>=x3:#x1大于其他每個

maxval=x1要完成該程序,我們只需要為其他可能性執行類似的測試:ifx1>=x2andx1>=x3:maxval=x1elifx2>=x1andx2>=x3:maxval=x2else:maxval=x33.4.4程序示例:尋找三個數中最大的一個我們的算法基本上是檢查了每個可能的值,以確定它是否最大。這在只有三個值時結果還是簡單的,但如果試圖找到五個值中最大的,解決方案恐怕就復雜或者說啰嗦了。3.4.4程序示例:尋找三個數中最大的一個2.策略2:判斷樹第二種方式是使用“判斷樹”方法。假設我們從一個簡單的測試x1>=x2開始。如果條件為真,只需要看看x1和x3哪個更大。如果條件為假,則結果歸結為x2和x3之間的選擇。第一個判斷“分支”有兩種可能性,每種又有另一個判斷,因此稱為“判斷樹”。下圖用流程圖展示了這種情況。這個流程圖很容易轉換成嵌套的if-else語句。三者最大問題的判斷樹方法的流程圖ifx1>=x2:ifx1>=x3:maxval=x1else:maxval=x3e1se:ifx2>=x3:maxval=x2e1se:maxval=x33.4.4程序示例:尋找三個數中最大的一個3.4.4程序示例:尋找三個數中最大的一個這個方法的優勢是效率。無論三個值的順序如何,該算法都將進行兩次比較,并將正確的值分配給maxval,但這種方法的結構比第一種復雜。3.4.4程序示例:尋找三個數中最大的一個3.策略3:順序處理如果面對一個包含有幾百個數字的集合,又沒有特定的順序,你將如何找到這個集合中最大的數字呢?通常我們會制定一個簡單的策略,即順序瀏覽列表,記錄到目前為止最大的數字。在程序設計中,我們使用變量maxval來記錄這個最大值,最后maxval將自動包含列表中的最大值,流程圖描述如圖所示。三者最大問題的順序方法的流程圖3.4.4程序示例:尋找三個數中最大的一個下面是對應的Python代碼:maxval=x1ifx2>maxval:maxval=x2ifx3>maxval:maxva1=x33.4.4程序示例:尋找三個數中最大的一個顯然,順序方法是三種算法中最好的,代碼簡單,只包含兩個簡單的判斷,并且順序處理比以前算法中使用的嵌套更容易理解。此外,這個思路能很好地擴展到更大的問題。最后一個解決方案可以擴展到更大的問題。我們可以輕松地編寫一個程序,允許將該算法折疊成一個循環,找到n個數字中最大的。每次取得一個值,并不斷重復使用單個變量x。每次比較最新的x和maxval的當前值,看它是否更大。【程序實例3-7】查找一系列數字中的最大值。#maxn.py#查找一系列數字的最大值defmain():n=int(input("一共有多少個數字?"))#將max設置為第一個值

maxval=float(input("輸入一個數字>>"))3.4.4程序示例:尋找三個數中最大的一個#現在比較n-1個連續值

foriinrange(n-1):x=float(input("輸入一個數字>>"))ifx>maxval:maxval=xprint("這個最大的值是",maxval)main()3.4.4程序示例:尋找三個數中最大的一個3.4.4程序示例:尋找三個數中最大的一個這段代碼利用嵌套在循環中的判斷來完成工作。在循環的每次迭代中,將到目前為止看到的最大值存入maxval。3.4.4程序示例:尋找三個數中最大的一個4.策略4:使用內置函數Python實際上有一個內置的返回最大參數的函數max,即: defmain(): x1,x2,x3=eval(input("請輸入三個值:")) print("最大的值是",max(x1,x2,x3))解決這個問題的嘗試展示了算法和程序設計中的一些重要思想。3.4.4程序示例:尋找三個數中最大的一個(1)存在多種實現方式。任何有價值的計算問題,都有多種解決方法。因此,不要急于編寫。想想你的設計,問自己是否存在更好的方法來處理這個問題。重要的是要找到一個正確的算法,力求清晰、簡單、高效、可擴展和優雅,一些直接的方法通常簡單、清楚、有效。(2)通用性好。通過考慮更通用的n個數的最大值問題,得到最佳解決方案。(3)不要重新發明輪子。第四個解決

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論