




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第3章賦值語(yǔ)句與分支結(jié)構(gòu)Python程序設(shè)計(jì)第3章賦值語(yǔ)句與分支結(jié)構(gòu)簡(jiǎn)單的程序一般遵循輸入、處理、輸出(IPO)模式。整個(gè)Python程序由許多模塊組成,模塊里含有程序語(yǔ)句,語(yǔ)句各有其意義并含有表達(dá)式,表達(dá)式則建立并操作對(duì)象。有了基本的構(gòu)建塊(標(biāo)識(shí)符和表達(dá)式),就可以更完整地描述各種Python語(yǔ)句。一些編程語(yǔ)言提供了異常處理機(jī)制,讓程序更具“防御性”。Python的異常處理機(jī)制是try-except語(yǔ)句。初識(shí)語(yǔ)句1分支語(yǔ)句4賦值語(yǔ)句2input賦值語(yǔ)句3pass語(yǔ)句6目錄異常處理機(jī)制53.1初識(shí)語(yǔ)句語(yǔ)句基本概念表達(dá)式語(yǔ)句特有的縮進(jìn)3.1
初識(shí)語(yǔ)句語(yǔ)句是Python程序里最小最基本的執(zhí)行單位,每種語(yǔ)句都有其獨(dú)特的語(yǔ)法和語(yǔ)義。不符合語(yǔ)句的語(yǔ)法,就不是合法的程序代碼,也就不能被解釋器正確解析并執(zhí)行。而學(xué)習(xí)編寫Python程序,也就是學(xué)習(xí)各種語(yǔ)句所代表的意思,再加上表達(dá)式,表達(dá)出你想要的程序行為。3.1.1語(yǔ)句基本概念Python語(yǔ)句可分為簡(jiǎn)單語(yǔ)句與復(fù)合語(yǔ)句,大致上可以這么認(rèn)為:能寫成一行程序代碼的是簡(jiǎn)單語(yǔ)句,跨越好幾行的是復(fù)合語(yǔ)句。某些簡(jiǎn)單語(yǔ)句可以跨好幾行,但事實(shí)上Python解釋器會(huì)把它們當(dāng)作同一行看待;有時(shí)復(fù)合語(yǔ)句的程序碼太短了,因此Python語(yǔ)法也允許寫在同一行上。表3-1了列出Python的所有語(yǔ)句。3.1.1語(yǔ)句基本概念表3-1語(yǔ)句一覽表3.1.2表達(dá)式語(yǔ)句任何表達(dá)式同時(shí)也都是合法的語(yǔ)句,所以“3”、“3+5”、“3<5”、“x<yorz<x”等等,它們既是表達(dá)式也是語(yǔ)句,因此我們可以在Python解釋器的互動(dòng)模式里輸入“3”并執(zhí)行。Python程序可使用分號(hào)“;”標(biāo)示語(yǔ)句的結(jié)尾,但也可以不寫;但若使用分號(hào),便可把多個(gè)語(yǔ)句寫在同一行上。實(shí)際開(kāi)發(fā)中很少把多個(gè)語(yǔ)句寫在同一行上,因?yàn)檫@樣會(huì)導(dǎo)致程序的可讀性差。>>>1+2 #表達(dá)式也是合法語(yǔ)句3>>>1+2; #以分號(hào)“;”標(biāo)示語(yǔ)句結(jié)尾3>>>1+2;3+4;5+6; #以分號(hào)“;”隔開(kāi)語(yǔ)句37113.1.2表達(dá)式語(yǔ)句3.1.3特有的縮進(jìn)Python使用縮排來(lái)標(biāo)示程序代碼的層級(jí),所以語(yǔ)法非常簡(jiǎn)潔,不同于C/C++/Java/C#/JavaScript以大括號(hào)“{}”包住一堆程序代碼的方式。不過(guò)第一次接觸縮排格式的人會(huì)很不習(xí)慣,有道是:“若能搞懂縮排,就已經(jīng)搞懂Python語(yǔ)法的一半了”。Python語(yǔ)法規(guī)定,縮排可以是四個(gè)空格(建議)、兩個(gè)空格、一個(gè)TAB鍵或任何其他組合,重點(diǎn)在于保持一致、不要混用。本書(shū)的程序中一律采用四個(gè)空格的方式。3.2
賦值語(yǔ)句基本賦值語(yǔ)句多重賦值語(yǔ)句同時(shí)賦值語(yǔ)句增強(qiáng)賦值語(yǔ)句3.2
賦值語(yǔ)句Python中使用等號(hào)(=)表示將值賦給變量。利用賦值,程序可以從鍵盤獲得輸入。Python還允許同時(shí)賦值,這對(duì)于利用單個(gè)提示獲取多個(gè)輸入值很有用處。賦值語(yǔ)句是Python中重要的語(yǔ)句之一,務(wù)必完整且清楚地了解賦值語(yǔ)句。3.2.1基本賦值語(yǔ)句基本賦值語(yǔ)句具有以下形式:<標(biāo)識(shí)符>=<表達(dá)式>執(zhí)行賦值語(yǔ)句時(shí),解釋器先執(zhí)行等號(hào)右邊的表達(dá)式,得到結(jié)果(對(duì)象)后,再賦值給等號(hào)左邊的名稱,將該值與左側(cè)命名的變量相關(guān)聯(lián),建立起名稱與對(duì)象之間的關(guān)系,我們其為“綁定”。例如:>>>a=3 #建立int對(duì)象值為3,產(chǎn)生名稱a(第一次),賦值>>>b=3+5 #運(yùn)算結(jié)果是整數(shù)對(duì)象8,取名為b>>>c=a<b #運(yùn)算結(jié)果是bool對(duì)象,值為True,c指向此對(duì)象>>>a=a+1 #運(yùn)算結(jié)果是個(gè)新對(duì)象,a轉(zhuǎn)而指向該對(duì)象3.2.1基本賦值語(yǔ)句賦值語(yǔ)句左邊的名稱第一次出現(xiàn)時(shí),Python解釋器便會(huì)建立此名稱。該名稱可以多次被賦值,但它只保留最新賦的值。后面出現(xiàn)的賦值會(huì)使該名稱轉(zhuǎn)而指向別的對(duì)象,也就是建立新的綁定關(guān)系。所以,在上述程序代碼里,“a=3”是第一次建立a,解釋器會(huì)產(chǎn)生該名稱并指向int對(duì)象3;之后執(zhí)行“a=a+1”時(shí),先運(yùn)算右邊,得到新的int對(duì)象4,然后讓a轉(zhuǎn)而指向該對(duì)象,這個(gè)語(yǔ)句展示了如何使用名稱的當(dāng)前值來(lái)更新它的值。名稱的值可以改變,這就是為什么它們被稱為“變量”的原因。我們可以將“變量”看作是計(jì)算機(jī)內(nèi)存中的一種命名的存儲(chǔ)位置,可以在其中放入一個(gè)值。當(dāng)變量更改時(shí),舊值被刪除并寫入一個(gè)新值。3.2.1基本賦值語(yǔ)句如果一個(gè)值不再被任何名稱所引用,它就不再有用。Python將自動(dòng)從內(nèi)存中清除這些值,以便收回存儲(chǔ)空間。現(xiàn)在,大家應(yīng)該很清楚“名稱”、“變量”、“對(duì)象”和“類型”的關(guān)系了。但有時(shí)候我們會(huì)以不同的說(shuō)法描述,當(dāng)我們說(shuō):·“對(duì)象a”時(shí),正確說(shuō)法是“名稱a指向的那個(gè)對(duì)象”;·“對(duì)象a是個(gè)int”時(shí),正確說(shuō)法是“名稱a指向的對(duì)象,類型是int”;·“浮點(diǎn)數(shù)3.14”時(shí),正確說(shuō)法是“有個(gè)類型為?oat的對(duì)象,其值為3.14”;·“3是個(gè)整數(shù)對(duì)象”時(shí),正確說(shuō)法是“執(zhí)行程序代碼3后會(huì)建立類型為int的對(duì)象,其值為3”;·“整數(shù)對(duì)象a為3”時(shí),正確說(shuō)法是“名稱a指向類型int的對(duì)象,其值為3”;3.2.1基本賦值語(yǔ)句·“字符串s”時(shí),正確說(shuō)法是“名稱s指向的對(duì)象,其類型是str”;·“tuple類型不可變”時(shí),正確說(shuō)法是“類型tuple的對(duì)象一旦建立,其內(nèi)容就不會(huì)改變”;·“l(fā)ist對(duì)象li”時(shí),正確說(shuō)法是“名稱li指向類型為list的對(duì)象”;·“l(fā)ist是可變對(duì)象”時(shí),正確說(shuō)法是“類型為list的對(duì)象是可變的”;·“t是個(gè)tuple”時(shí),正確說(shuō)法是“名稱t指向類型為tuple的對(duì)象”。3.2.2多重賦值語(yǔ)句所謂多重賦值,是指在同一行內(nèi),讓同一個(gè)對(duì)象賦值(綁定)到多個(gè)名稱,以及用分號(hào)“;”隔開(kāi)多個(gè)賦值語(yǔ)句。在使用多重賦值時(shí),要當(dāng)心可變對(duì)象與不可變對(duì)象的差別。上述程序代碼中,因?yàn)閕nt對(duì)象3不可變,所以透過(guò)名稱a、b與c無(wú)法修改所指向的int對(duì)象3。若是可變的list對(duì)象,則透過(guò)y修改該對(duì)象的話,那么x指向的對(duì)象也變了,因?yàn)閤與y指向的對(duì)象是同一個(gè)。(想一想?)>>>a=b=c=3 #a、b、c都指向同一個(gè)int對(duì)象3>>>b=4;c=5 #以分號(hào)隔開(kāi)兩個(gè)語(yǔ)句,重新賦值b與c>>>a3>>>x=y=z=[0,1,2]#都指向同一個(gè)list對(duì)象>>>y[0]=99 #list是可變對(duì)象,修改>>>z=[30,41,52] #名稱z轉(zhuǎn)而指向新對(duì)象>>>x,y,z #x與y指向同一個(gè)對(duì)象([99,1,2],[99,1,2],[30,41,52])3.2.2多重賦值語(yǔ)句3.2.3同時(shí)賦值語(yǔ)句若想把多個(gè)對(duì)象在同一行內(nèi)賦值給多個(gè)名稱,可使用“同時(shí)賦值”(又稱“序列賦值”),即一個(gè)賦值語(yǔ)句允許同時(shí)計(jì)算幾個(gè)值。它看起來(lái)像這樣: <名稱1>,<名稱2>,...,<名稱n>=<表達(dá)式1>,<表達(dá)式2>,...,<表達(dá)式n>它告訴Python對(duì)右側(cè)所有表達(dá)式求值,然后將這些值賦給左側(cè)命名的相應(yīng)名稱。例如: sum,diff=x+y,x-y這里,sum得到x和y的和,diff得到x和y的差。3.2.3同時(shí)賦值語(yǔ)句這種形式的賦值實(shí)際上非常有用。例如:假設(shè)有兩個(gè)變量x和y,你希望交換它們的值。也就是說(shuō),你希望將當(dāng)前存儲(chǔ)在x中的值存儲(chǔ)在y中,將當(dāng)前存儲(chǔ)在y中的值存儲(chǔ)在x中。下面這樣做是不行的: x=y y=x因?yàn)樽罱K得到了原始y值的兩個(gè)副本(想一想為什么?)。3.2.3同時(shí)賦值語(yǔ)句完成交換的一種方法是引入一個(gè)附加變量,它暫時(shí)記住x的原始值。 temp=x x=y y=temp這種三變量交換的方式在其他編程語(yǔ)言中很常見(jiàn)。在Python中,同時(shí)賦值語(yǔ)句提供了一種優(yōu)雅的選擇。下面是簡(jiǎn)單的Python等價(jià)寫法,因?yàn)橘x值是同時(shí)的: x,y=y,x又例如:>>>(a,b,c)=(0,1,2) #左邊是tuple(元組,不可變的列表)>>>a,b,c=0,1,2 #tuple可省略括號(hào)>>>a,b=b,a #交換a與b所指向的對(duì)象>>>a,b #a,b原來(lái)是(0,1)(1,0) #現(xiàn)在是(1,0)>>>x=[0,1];i=0>>>i,x[i]=1,2 #注意i先成為1,然后才賦值x[i]>>>x[0,2] #所以是x[1]變了3.2.3同時(shí)賦值語(yǔ)句3.2.3同時(shí)賦值語(yǔ)句不僅可以使用元組(tuple),也可以使用方括號(hào)(list);使用這種賦值語(yǔ)句時(shí),等號(hào)右邊可以是任何序列類型,例如list、tuple、str等。 >>>a,b,c=[0,1,2] #等號(hào)右邊可以是list對(duì)象 >>>[a,b,c]=[0,1,2] #等號(hào)左邊也可以使用方括號(hào) >>>a,b,c='abc' #等號(hào)右邊可以是str對(duì)象 >>>a,b,c #查看,a、b、c分別指向一個(gè)str對(duì)象 ('a','b','c') #每個(gè)str對(duì)象只含一個(gè)字元 >>>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同時(shí)賦值語(yǔ)句“序列賦值”最好用的情況是當(dāng)你知道某容器對(duì)象的內(nèi)部結(jié)構(gòu)時(shí),可以迅速地把其內(nèi)容抽取出來(lái),例如上面的data。使用此種賦值能減少程序代碼行數(shù),但實(shí)際開(kāi)發(fā)時(shí),應(yīng)把相關(guān)的數(shù)據(jù)放在一起、不相關(guān)的分開(kāi),這樣才能讓程序代碼易讀易懂。上面的序列賦值,語(yǔ)句左右兩邊的個(gè)數(shù)必須相同,否則會(huì)發(fā)生錯(cuò)誤。此外,“星號(hào)序列賦值”適合用于長(zhǎng)度不定或未知的情況。例如:>>>x=[0,1,2,3,4]>>>a,*b,c=x #星號(hào),其余元素通通都會(huì)放進(jìn)b>>>a,b,c(0,[1,2,3],4)#b是個(gè)列表對(duì)象>>>head,*rest=x #拿出x列表里的第0個(gè)元素>>>head,rest #剩余的通通放進(jìn)rest(0,[1,2,3,4])>>>*rest,t1,t0=x #拿出倒數(shù)兩個(gè)元素>>>rest,t1,t0 #剩余的通通放進(jìn)rest([0,1,2],3,4)3.2.3同時(shí)賦值語(yǔ)句>>>a0,a1,a2,a3,*a4=x#注意,當(dāng)兩邊個(gè)數(shù)相等時(shí),>>>a0,a1,a2,a3,a4#以星號(hào)標(biāo)示的名稱a4,(0,1,2,3,[4]) #仍然會(huì)是list對(duì)象>>>a0,a1,a2,a3,*a4,a5=x>>>a0,a1,a2,a3,a4,a5#當(dāng)左邊名稱個(gè)數(shù)多于右邊時(shí),(0,1,2,3,[],4) #以星號(hào)標(biāo)示的名稱會(huì)指向空列表,3.2.3同時(shí)賦值語(yǔ)句>>>a0,*a1,*a2,a3=x#此種形式的兩個(gè)星號(hào),發(fā)生錯(cuò)誤
File"<stdin>",line1a0,*a1,*a2,a3^SyntaxError:invalidsyntax#語(yǔ)法錯(cuò)誤:無(wú)效語(yǔ)法>>>record=('John',50,123.45,(12,18,2012))>>>name,*_,(*_,year)=record #這種形式的兩個(gè)星號(hào),合法想要的才取名稱,>>>name,year#不需要的東西就隨便給個(gè)名稱,例如下劃線“_”('John',2012)3.2.3同時(shí)賦值語(yǔ)句3.2.4增強(qiáng)賦值語(yǔ)句增強(qiáng)賦值語(yǔ)句是指運(yùn)算符中有“+=、-=、*=、/=、//=、%=、**=、>>=、<<=、&=、^=、|=”。以“x+=y”為例,其語(yǔ)義“幾乎”等同于“x=x+y”,實(shí)際行為必須視語(yǔ)句左邊的對(duì)象是否為可變對(duì)象而定。例如:>>>a=b=3>>>a+=8 #等同于a=a+8>>>(a,b) #因?yàn)閕nt對(duì)象不可變(11,3) #a、b指向不同的對(duì)象>>>x=y=[0,1,2] #x與y指向同一個(gè)可變對(duì)象>>>x+=[98,99] #注意:這會(huì)改變x指向的對(duì)象>>>x,y([0,1,2,98,99],[0,1,2,98,99])>>>xisy #x跟y是同一個(gè)對(duì)象True3.2.4增強(qiáng)賦值語(yǔ)句>>>x=y=[0,1,2] #讓我們?cè)僭囈淮危?gt;>>x=x+[98,99] #這次使用表達(dá)式x+[98,99]>>>x,y #名稱x會(huì)轉(zhuǎn)而指向運(yùn)算后的新對(duì)象([0,1,2,98,99],[0,1,2])>>>xisy #x與y不是同一個(gè)對(duì)象False3.2.4增強(qiáng)賦值語(yǔ)句3.2.4增強(qiáng)賦值語(yǔ)句執(zhí)行“x+=y”時(shí),若x是不可變對(duì)象,那么其行為等同于“x=x+y”;但若x是可變對(duì)象,那么“x+=y”將會(huì)修改x對(duì)象而不是產(chǎn)生新對(duì)象,這種行為叫做“原地修改”;而“x=x+[98,99]”則是由表達(dá)式“x+[98,99]”產(chǎn)生新的對(duì)象,再指派給名稱x。請(qǐng)仔細(xì)琢磨這一段的含義。3.3
input賦值語(yǔ)句3.3
input賦值語(yǔ)句輸入語(yǔ)句的目的是從程序的用戶那里獲取信息并存儲(chǔ)到變量中。在Python中,輸入是用一個(gè)賦值語(yǔ)句結(jié)合一個(gè)內(nèi)置函數(shù)input實(shí)現(xiàn)的。輸入語(yǔ)句的具體形式,取決于你希望從用戶那里獲取的數(shù)據(jù)類型。對(duì)于文本輸入,語(yǔ)句如下所示: <變量>=input(<字符串表達(dá)式>)這里的<字符串表達(dá)式>用于提示用戶輸入,該提示幾乎總是一個(gè)字符串字面量(即引號(hào)內(nèi)的一些文本)。3.3
input賦值語(yǔ)句當(dāng)Python遇到對(duì)input的調(diào)用時(shí),它在屏幕上打印提示。然后,暫停并等待用戶鍵入一些文本,鍵入完成后按回車鍵。用戶輸入的任何東西都會(huì)存儲(chǔ)為字符串,例如: >>>name=input("請(qǐng)輸入你的名字:")請(qǐng)輸入你的名字:xiaoming >>>name 'xiaoming'執(zhí)行input語(yǔ)句時(shí)Python打印輸出提示“請(qǐng)輸入你的名字:”,然后解釋器暫停,等待用戶輸入。在這個(gè)例子中鍵入xiaoming(小明),結(jié)果字符串“xiaoming”被記在名稱name中。對(duì)name求值將返回鍵入的字符串。3.3
input賦值語(yǔ)句如果希望接收的是用戶輸入的一個(gè)數(shù)字,就需要形式稍復(fù)雜一點(diǎn)的input語(yǔ)句: <變量>=eval(input(<字符串表達(dá)式>))這里添加了另一個(gè)Python的內(nèi)置函數(shù)eval,它內(nèi)嵌了input函數(shù)。eval是“evaluate(求值)”的縮寫。在這種形式中,用戶鍵入的文本被求值為一個(gè)表達(dá)式,以產(chǎn)生存儲(chǔ)到變量中的值。例如字符串“32”被轉(zhuǎn)換成數(shù)字32: x=eval(input("請(qǐng)輸入0到1之間的數(shù)字:")) celsius=eval(input("攝氏溫度是多少?"))應(yīng)該在提示結(jié)尾處的引號(hào)內(nèi)安排一個(gè)空格,以使用戶輸入的內(nèi)容不會(huì)緊挨著提示開(kāi)始,讓交互更容易閱讀和理解。3.3
input賦值語(yǔ)句雖然數(shù)字示例特別提示用戶輸入數(shù)字,但實(shí)際上用戶鍵入的只是一個(gè)數(shù)字字面量,即一個(gè)簡(jiǎn)單的Python表達(dá)式。事實(shí)上,任何有效的表達(dá)式都是可接受的。請(qǐng)考慮下面與Python解釋器的交互: >>>ans=eval(input("請(qǐng)輸入一個(gè)表達(dá)式:"))請(qǐng)輸入一個(gè)表達(dá)式:3+4*5 >>>print(ans) 23 >>>這里,提示輸入表達(dá)式時(shí),用戶鍵入“3+4*5”,Python通過(guò)eval對(duì)此表達(dá)式求值,并將值賦給變量ans。打印時(shí),我們看到ans的值為23,與預(yù)期一樣。不同的是,用戶在語(yǔ)句執(zhí)行時(shí)提供的是表達(dá)式。3.3
input賦值語(yǔ)句eval函數(shù)功能很強(qiáng)大,但也有“潛在的危險(xiǎn)”。如本例所示,當(dāng)我們對(duì)用戶輸入求值時(shí),本質(zhì)上是允許用戶輸入一部分程序。Python將盡職盡責(zé)地對(duì)他們輸入的任何內(nèi)容求值,了解Python的人就有可能利用這種能力輸入惡意指令。例如,用戶可以鍵入記錄計(jì)算機(jī)上的私人信息或刪除文件的表達(dá)式。在計(jì)算機(jī)安全中,這被稱為“代碼注入”攻擊,因?yàn)楣粽邔阂獯a注入正在運(yùn)行的程序中。【程序?qū)嵗?-1】用單個(gè)input從用戶那里獲取多個(gè)數(shù)字,求出考試平均分。#avg.py#計(jì)算兩個(gè)考試分?jǐn)?shù)的平均值的簡(jiǎn)單程序,用來(lái)說(shuō)明多個(gè)輸入的使用。defmain():print("這個(gè)程序計(jì)算兩個(gè)考試分?jǐn)?shù)的平均值。")score1,score2=eva1(input("輸入以逗號(hào)分隔的兩個(gè)分?jǐn)?shù):"))average=(score1+score2)/2print("分?jǐn)?shù)的平均值是:",average)main()請(qǐng)記錄:上面代碼的運(yùn)行結(jié)果_________________________________________________3.3
input賦值語(yǔ)句3.3
input賦值語(yǔ)句該程序提示用逗號(hào)分隔兩個(gè)分?jǐn)?shù),例如input語(yǔ)句的效果就像進(jìn)行以下賦值: score1,score2=86,92這個(gè)例子可以擴(kuò)展到任意數(shù)量的輸入。當(dāng)然,也可以通過(guò)單獨(dú)的input語(yǔ)句獲得用戶的輸入: score1=eval(input("輸入第一個(gè)分?jǐn)?shù):")) score2=eval(input("輸入第二個(gè)分?jǐn)?shù):"))某種程度上,這可能更好,因?yàn)閱为?dú)的提示對(duì)用戶來(lái)說(shuō)信息更準(zhǔn)確。有時(shí)在單個(gè)input中獲取多個(gè)值提供了更直觀的用戶接口。但要記住,多個(gè)值的技巧不適用于字符串(非求值)輸入,如果用戶鍵入逗號(hào),它只是輸入字符串中的一個(gè)字符。3.4
分支語(yǔ)句簡(jiǎn)單分支語(yǔ)句復(fù)雜分支語(yǔ)句多重條件分支語(yǔ)句程序示例:尋找三個(gè)數(shù)中最大的一個(gè)3.4
分支語(yǔ)句計(jì)算機(jī)程序是指令的序列,序列是編程的一個(gè)基本概念。但是,只用序列不足以解決所有問(wèn)題,實(shí)踐中常常需要改變程序的順序流程,以適應(yīng)特定情況的需要。這是通過(guò)稱為“控制結(jié)構(gòu)”的特殊語(yǔ)句來(lái)完成的。“判斷”是允許程序針對(duì)不同情況執(zhí)行不同指令序列的控制結(jié)構(gòu),實(shí)際上允許程序“選擇”適當(dāng)?shù)膭?dòng)作過(guò)程。條件語(yǔ)句根據(jù)表達(dá)式的運(yùn)算結(jié)果(True或False)來(lái)判斷應(yīng)該執(zhí)行哪部分的程序代碼(分支),控制程序走向,我們稱呼此類的語(yǔ)句為程序流控制。3.4
分支語(yǔ)句在Python中,簡(jiǎn)單的判斷用一個(gè)if語(yǔ)句來(lái)實(shí)現(xiàn),兩路判斷通常使用if-else,多路判斷用if-elif-else實(shí)現(xiàn)。如果判斷結(jié)構(gòu)是嵌套的,則結(jié)合判斷的算法可能會(huì)變得相當(dāng)復(fù)雜。在程序設(shè)計(jì)過(guò)程中,通常有許多解決方案可選,程序員應(yīng)仔細(xì)考慮,得到正確、有效和可理解的程序。判斷基于條件的求值,條件是簡(jiǎn)單的布爾表達(dá)式,其運(yùn)算結(jié)果為True或False。Python有專門的布爾數(shù)據(jù)類型,其字面量為True和False。條件的構(gòu)成利用了關(guān)系運(yùn)算符<、<=、!=、==、>和>=。3.4
分支語(yǔ)句if語(yǔ)句的一般形式如下,其中elif與else為可選項(xiàng),elif也可以有好幾個(gè):if表達(dá)式:
語(yǔ)句語(yǔ)句...elif表達(dá)式:
語(yǔ)句語(yǔ)句...else:
語(yǔ)句語(yǔ)句...3.4
分支語(yǔ)句if、elif、else那一行的最后面必須加上冒號(hào)“:“,代表后面接著一組程序語(yǔ)句,而里面的語(yǔ)句必須縮排。在上面的程序代碼里,因?yàn)楸磉_(dá)式“a<b”為真,所以會(huì)進(jìn)入if內(nèi)的程序代碼,若“a<b”的結(jié)果為假,就會(huì)跳過(guò)不執(zhí)行。當(dāng)輸入“ifa<b:”時(shí),若解釋器處于互動(dòng)模式,會(huì)輸出“...”提醒你這不是有效語(yǔ)句,無(wú)法執(zhí)行,要求你繼續(xù)輸入,而在冒號(hào)“:”之下的程序代碼必須縮排。“ifa<b:”之后的程序代碼可含有多個(gè)語(yǔ)句(此例中只有一個(gè)),然后直接按回車鍵輸入空行,代表結(jié)束;在解釋器互動(dòng)模式下才須如此,若是寫在文件中就不需要了。例如:>>>a=3 #a之前沒(méi)有空格>>>a=3 #a之前有一個(gè)空格,發(fā)生錯(cuò)誤
File"<stdin>",line1a=3^IndentationError:unexpectedindent#縮排錯(cuò)誤:未預(yù)期縮排>>>a,b,x=3,5,-1>>>ifa<b: #如果a小于b...x=a #讓x指向?qū)ο骯;在x之前輸入四個(gè)空格... #直接按回車鍵輸入空行,代表結(jié)束if語(yǔ)句>>>x #x指向333.4
分支語(yǔ)句3.4.1簡(jiǎn)單分支語(yǔ)句我們簡(jiǎn)單判斷開(kāi)始。作為一個(gè)例子,先回顧一下攝氏溫度轉(zhuǎn)換為華氏溫度的程序(參見(jiàn)程序?qū)嵗?-1)。我們來(lái)加強(qiáng)這個(gè)程序,以確保在溫度極端(相當(dāng)熱或相當(dāng)冷)時(shí)程序能打印出適當(dāng)?shù)木嫣崾尽?.4.1簡(jiǎn)單分支語(yǔ)句第一步是給出完整的增強(qiáng)規(guī)格說(shuō)明。假設(shè)當(dāng)溫度超過(guò)90華氏度時(shí)應(yīng)該發(fā)出熱警告,而低于30華氏度時(shí)則會(huì)發(fā)出冷警告。為此,設(shè)計(jì)一個(gè)擴(kuò)展的算法如下:以攝氏度輸入溫度值計(jì)算華氏溫度為9/5攝氏度+32輸出華氏度值如果華氏度>90
打印熱警告如果華氏度<30
打印冷警告這個(gè)設(shè)計(jì)在結(jié)束時(shí)有兩個(gè)簡(jiǎn)單的“判斷”。縮進(jìn)表示只有滿足上一行中列出的條件才執(zhí)行該步驟。判斷引入了一個(gè)替代的控制流,算法采取的步驟取決于華氏度的值。3.4.1簡(jiǎn)單分支語(yǔ)句如圖是一個(gè)流程圖,展示算法可能采取的路徑。菱形框表示有條件的判斷。如果條件為假,則控制傳遞到序列中的下一個(gè)語(yǔ)句;如果條件成立,則控制權(quán)轉(zhuǎn)移到右側(cè)框中的指令,這些指令完成后,控制會(huì)傳遞到下一個(gè)語(yǔ)句。
帶有警告的溫度轉(zhuǎn)換程序流程圖【程序?qū)嵗?-2】帶溫度警告的攝氏溫度轉(zhuǎn)換為華氏溫度的Python程序。#convert2.py#將攝氏溫度轉(zhuǎn)換為華氏溫度的程序。此版本發(fā)出熱和冷警告defmain():celsius=float(input("攝氏溫度是多少?"))fahrenheit=9/5*celsius+32print("溫度是",fahrenheit,"華氏度。")#打印極端溫度警告
iffahrenheit>90:print("那里真的很熱。小心!")iffahrenheit<30:print("特別提醒,一定要穿得暖和些!")main()3.4.1簡(jiǎn)單分支語(yǔ)句3.4.1簡(jiǎn)單分支語(yǔ)句可以看到,Python的if語(yǔ)句用于實(shí)現(xiàn)判斷。if<條件>:<序列>這里<序列>是if頭部下縮進(jìn)的一個(gè)或多個(gè)語(yǔ)句的序列。在convert2.py中有兩個(gè)if語(yǔ)句,每個(gè)<序列>中都有一個(gè)語(yǔ)句。可見(jiàn),if的語(yǔ)義是:首先,對(duì)頭部中的條件求值。如果條件為真,則執(zhí)行<序列>中的語(yǔ)句,然后控制傳遞到程序中的下一條語(yǔ)句;如果條件為假,則跳過(guò)<序列>中的語(yǔ)句。If的<序列>是否執(zhí)行取決于條件,不論哪種情況,控制隨后會(huì)傳遞到if后的下一個(gè)語(yǔ)句,這是“一路”判斷或“簡(jiǎn)單”判斷。簡(jiǎn)單if語(yǔ)句的控制流3.4.1簡(jiǎn)單分支語(yǔ)句2.形成簡(jiǎn)單條件上述程序使用的簡(jiǎn)單條件比較兩個(gè)表達(dá)式的值:<expr><relop><expr>。<relop>是“關(guān)系運(yùn)算符”的縮寫,是“小于”或“等于”這類數(shù)學(xué)概念的特別名稱。Python中有6個(gè)關(guān)系運(yùn)算符。表3-2Python中的關(guān)系運(yùn)算符3.4.1簡(jiǎn)單分支語(yǔ)句特別要注意用“==”表示相等。由于Python已經(jīng)使用“=”符號(hào)來(lái)表示賦值語(yǔ)句,因此對(duì)于相等概念,需要使用不同的符號(hào)。條件可以用于比較數(shù)字或字符串。比較字符串時(shí),排序是根據(jù)底層的Unicode值以字母順序放置的字符串。因此,所有大寫拉丁字母都在小寫字母之前(例如,“Bbbb”在“aaaa”之前,因?yàn)椤癇”在“a”之前)。條件實(shí)際上是一種布爾表達(dá)式,對(duì)它求值會(huì)產(chǎn)生值True(條件成立)或False(條件不成立)。某些語(yǔ)言(如C++)用整數(shù)1和0來(lái)表示這些值。在Python中,布爾表達(dá)式類型為bool,布爾值true和false由字面量True和False表示。下面是一些交互示例: >>>3<4 True >>>3*4<3+4 False >>>"hello"=="hello" True >>>"hello"<"hello" False >>>"Hello"<"hello" True3.4.1簡(jiǎn)單分支語(yǔ)句3.4.1簡(jiǎn)單分支語(yǔ)句3.條件程序執(zhí)行運(yùn)行Python程序有幾種不同的方式。一些Python模塊文件被設(shè)計(jì)為直接運(yùn)行,這些通常被稱為“程序”或“腳本”。其他Python模塊主要設(shè)計(jì)為讓其他程序?qū)牒褪褂茫@些通常被稱為“庫(kù)”。有時(shí)我們希望創(chuàng)建一種混合模塊,它既可以作為獨(dú)立程序使用,也可以作為由其他程序?qū)氲膸?kù)使用。到目前為止,我們編寫的大多數(shù)程序在底部有一行main()來(lái)調(diào)用main函數(shù),啟動(dòng)該程序的運(yùn)行,這些程序適合直接運(yùn)行。在窗口環(huán)境中,可以通過(guò)點(diǎn)擊(或雙擊)圖標(biāo)來(lái)運(yùn)行該文件,或者鍵入類似Python<myfile>這樣的命令。3.4.1簡(jiǎn)單分支語(yǔ)句由于Python在導(dǎo)入過(guò)程中對(duì)模塊中的行求值,所以當(dāng)前程序在導(dǎo)入到交互式Python會(huì)話或另一個(gè)Python程序時(shí)也會(huì)運(yùn)行。一般來(lái)說(shuō),不要讓模塊在導(dǎo)入時(shí)運(yùn)行。以交互方式測(cè)試程序時(shí),通常的方法是首先導(dǎo)入模塊,然后在每次運(yùn)行時(shí)調(diào)用它的main(或一些其他函數(shù))。如果程序設(shè)計(jì)為既可以導(dǎo)入(不運(yùn)行)又可以直接運(yùn)行,則對(duì)底部的main的調(diào)用必須是有條件的。一個(gè)簡(jiǎn)單的判斷應(yīng)該就能搞定,我們只需要找到合適的條件: if<條件>: main()無(wú)論何時(shí)導(dǎo)入模塊,Python都會(huì)在該模塊內(nèi)部創(chuàng)建一個(gè)特殊的變量__name__,并為其分配一個(gè)表示模塊名稱的字符串。3.4.1簡(jiǎn)單分支語(yǔ)句下面是一個(gè)示例交互,顯示math庫(kù)的情況: >>>importmath >>>math.__name__ 'math'可以看到,在導(dǎo)入后,math模塊中的__name__變量賦為字符串“math”。但是,如果直接運(yùn)行Python代碼(不導(dǎo)入),Python會(huì)將__name__的值設(shè)置為 “__main__”。 >>>__name__ '__main__'3.4.1簡(jiǎn)單分支語(yǔ)句例如,我們可以改變程序的最后一行,像這樣: if__name__=='__main__’: main()這保證在直接調(diào)用程序時(shí)自動(dòng)運(yùn)行main,但如果導(dǎo)入模塊,就不會(huì)運(yùn)行。幾乎在每個(gè)Python程序的底部,都會(huì)看到類似這樣的一行代碼。3.4.2復(fù)雜分支語(yǔ)句if語(yǔ)句還可以加上elif與else做更復(fù)雜的條件判斷。我們稱elif與else為子句,它們不可獨(dú)立存在,屬于if語(yǔ)句的一部分。>>>t=999;x=None #以None代表無(wú)效值>>>ift<0: #如果if為真...x=-1 #執(zhí)行此處...elif0<=tandt<=100: #如果if為假而這里為真...x=t #執(zhí)行此處...else: #如果之前皆為假...x=101 #執(zhí)行此處... #以此例而言,最后x會(huì)是101...elif #若只輸入elif或elseFile"<stdin>",line1elif^SyntaxError:invalidsyntax#語(yǔ)法錯(cuò)誤:無(wú)效語(yǔ)法3.4.2復(fù)雜分支語(yǔ)句3.4.2復(fù)雜分支語(yǔ)句執(zhí)行if/elif/elif.../else組成的語(yǔ)句時(shí),會(huì)從上到下逐一判斷if與elif的表達(dá)式是否為真,若為真便執(zhí)行對(duì)應(yīng)的程序代碼,然后跳到語(yǔ)句組之后繼續(xù)執(zhí)行;若所有的if與elif皆為假,便會(huì)執(zhí)行else子句(如果有的話)的程序代碼。3.4.2復(fù)雜分支語(yǔ)句if語(yǔ)句內(nèi)部還可以有if語(yǔ)句,形成嵌套結(jié)構(gòu),例如,下面的操作是找出a、b、c三個(gè)數(shù)中最大的一個(gè):>>>a,b,c=3,5,7;x=None>>>ifa<b: #縮排零層...ifb<c: #縮排一層...x=c #縮排二層...else: #縮排一層...x=b #縮排二層...else: #縮排零層...ifa<c: #縮排一層3.4.2復(fù)雜分支語(yǔ)句...x=c #縮排二層...else: #縮排一層...x=a #縮排二層... #最后x會(huì)是a、b、c中最大的...ifa<b #忘記冒號(hào)“:”File"<stdin>",line1ifa<b^SyntaxError:invalidsyntax#語(yǔ)法錯(cuò)誤:無(wú)效語(yǔ)法在if語(yǔ)句中嵌套if語(yǔ)句時(shí),必須再多縮排一層,這樣Python解釋器才能看懂程序代碼。【程序?qū)嵗?-3】二次方程求解程序。#quadratic.py#計(jì)算二次方程實(shí)根的程序,說(shuō)明數(shù)學(xué)庫(kù)的使用#如果方程沒(méi)有真正的根,該程序會(huì)崩潰importmath #使數(shù)學(xué)庫(kù)可用defmain():print("該程序找到二次方程的真實(shí)解。")print()a=float(input("輸入系數(shù)a:"))3.4.2復(fù)雜分支語(yǔ)句b=float(input("輸入系數(shù)b:"))c=float(input("輸入系數(shù)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復(fù)雜分支語(yǔ)句3.4.2復(fù)雜分支語(yǔ)句程序注釋中指出,如果給出的系數(shù)造成沒(méi)有實(shí)根的二次方程時(shí),該程序會(huì)崩潰。這段代碼的問(wèn)題是當(dāng)b2-4ac小于0時(shí),程序試圖取負(fù)數(shù)的平方根。由于負(fù)數(shù)沒(méi)有實(shí)根,所以程序報(bào)告錯(cuò)誤。請(qǐng)看下面這個(gè)執(zhí)行的這個(gè)例子: >>>main()該程序找到二次方程的真實(shí)解。3.4.2復(fù)雜分支語(yǔ)句輸入系數(shù)a:1輸入系數(shù)b:2輸入系數(shù)c:3Traceback(mostrecentcalllast):File"quadratic.py",line23,in<module>main()File"quadratic.py",line16,inmaindiscRoot=math.sqrt(b*b–4*a*c)ValueError:mathdomainerror【程序?qū)嵗?-4】二次方程求解程序,增加一個(gè)判斷以保證程序不會(huì)崩潰。#quadratic2.pyimportmathdefmain():print("該程序找到二次方程的真實(shí)解。\n")a=float(input("輸入系數(shù)a:"))b=float(input("輸入系數(shù)b:"))c=float(input("輸入系數(shù)c:"))3.4.2復(fù)雜分支語(yǔ)句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復(fù)雜分支語(yǔ)句3.4.2復(fù)雜分支語(yǔ)句這個(gè)修改版本首先計(jì)算判別式(b2-4ac)的值,再檢查并確保它不是負(fù)數(shù)。然后程序繼續(xù)取平方根并計(jì)算解。如果dscrim為負(fù)數(shù),該程序?qū)⒉粫?huì)調(diào)用math.sqrt。下面是交互執(zhí)行的示例:>>>main()該程序找到二次方程的真實(shí)解。輸入系數(shù)a:1輸入系數(shù)b:2輸入系數(shù)c:3>>>3.4.2復(fù)雜分支語(yǔ)句當(dāng)方程沒(méi)有實(shí)根時(shí),即當(dāng)b*b–4*a*c小于零時(shí),程序?qū)⒑?jiǎn)單地跳過(guò)計(jì)算并轉(zhuǎn)到下一條語(yǔ)句。由于沒(méi)有下一條語(yǔ)句,程序就會(huì)退出。不過(guò),這幾乎比以前的版本更差,因?yàn)樗唤o用戶任何跡象表明發(fā)生什么錯(cuò)誤,只是讓程序中止。好的程序應(yīng)該打印一條消息,告訴用戶他們指定的方程沒(méi)有實(shí)數(shù)解。我們可以通過(guò)在程序結(jié)束時(shí)添加另一個(gè)簡(jiǎn)單的判斷來(lái)實(shí)現(xiàn)這一點(diǎn)。 ifdiscrim<0: print("這個(gè)等式?jīng)]有實(shí)數(shù)解!")但這個(gè)解決方案還有問(wèn)題。程序中有兩個(gè)條件但只有一個(gè)判斷。根據(jù)dscrim的值,程序應(yīng)該打印沒(méi)有實(shí)數(shù)根,或者計(jì)算并顯示根。這是一個(gè)兩路判斷的例子。3.4.2復(fù)雜分支語(yǔ)句在Python中,可以通過(guò)if-else語(yǔ)句,即在if子句后加上else子句來(lái)實(shí)現(xiàn)兩路判斷。if<條件>:<陳述>else:<陳述>當(dāng)Python解釋器遇到這種結(jié)構(gòu)時(shí),它首先對(duì)條件求值。如果條件為真,則執(zhí)行if下的語(yǔ)句;如果條件為假,則執(zhí)行else下的語(yǔ)句。在任何情況下,控制隨后都轉(zhuǎn)到if-else之后的語(yǔ)句。【程序?qū)嵗?-5】二次方程求解程序,使用兩路判斷,得到一個(gè)更好的解決方案。#quadratic3.pyimportmathdefmain():print("該程序找到二次方程的真實(shí)解。\n")a=float(input("輸入系數(shù)a:"))b=float(input("輸入系數(shù)b:"))c=float(input("輸入系數(shù)c:"))3.4.2復(fù)雜分支語(yǔ)句discrim=b*b-4*a*cifdiscrim<0:print("\n這個(gè)等式?jīng)]有實(shí)根!")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復(fù)雜分支語(yǔ)句3.4.2復(fù)雜分支語(yǔ)句下面是兩次運(yùn)行這個(gè)程序的示例會(huì)話:>>>main()該程序找到二次方程的真實(shí)解。輸入系數(shù)a:1輸入系數(shù)b:2輸入系數(shù)c:3這個(gè)等式?jīng)]有實(shí)根!3.4.2復(fù)雜分支語(yǔ)句>>>main()該程序找到二次方程的真實(shí)解。輸入系數(shù)a:2輸入系數(shù)b:4輸入系數(shù)c:1這組解是:-0.2928932188134524-1.7071067811865475>>>3.4.3多重條件分支語(yǔ)句程序示例3-5所示的二次方程求解程序改進(jìn)較大,但是還存在一些問(wèn)題。例如:>>>main()該程序找到二次方程的真實(shí)解。輸入系數(shù)a:1輸入系數(shù)b:2輸入系數(shù)c:1這組解是:-1.0-1.0這在技術(shù)上是正確的,給定的系數(shù)產(chǎn)生一個(gè)方程,有相等的根為-1。但是,輸出可能會(huì)使某些用戶感到困惑。程序應(yīng)該給出更多信息,以避免混亂。3.4.3多重條件分支語(yǔ)句當(dāng)discrim為0時(shí),發(fā)生等根的情況。在這種情況下,discRoot也為0,并且兩個(gè)根的值為-b。如果希望捕捉這種特殊情況,程序?qū)嶋H上需要一個(gè)三路判斷,即:…檢查discrim的值當(dāng)<0:處理沒(méi)有根的情況當(dāng)=0:處理雙根的情況當(dāng)>0:處理兩個(gè)不同根的情況。該算法的一種編碼方法是用兩個(gè)if-else語(yǔ)句。if或else子句的主體可以包含任何合法的Python語(yǔ)句,包括其他if或if-else語(yǔ)句。將一個(gè)復(fù)合語(yǔ)句放入另一個(gè)復(fù)合語(yǔ)句稱為“嵌套”。3.4.3多重條件分支語(yǔ)句下面是用嵌套來(lái)實(shí)現(xiàn)三路判斷的代碼片段:ifdiscrim<0:print("沒(méi)有實(shí)根!")else:ifdiscrim==0:root=-b/(2*a)print("有一個(gè)雙根",root)else:#有兩個(gè)不同的根3.4.3多重條件分支語(yǔ)句仔細(xì)觀察這段代碼,會(huì)看到有三種可能的路徑。代碼序列由dscrim的值確定。該解決方案的流程圖如圖所示。你可以看到頂層結(jié)構(gòu)只是一個(gè)if-else(將虛線框視為一個(gè)大語(yǔ)句)。虛線框包含第二個(gè)if-else,嵌套在頂級(jí)判斷的else部分中。
使用嵌套if-else的二次求解器的三路判斷3.4.3多重條件分支語(yǔ)句這個(gè)解決方案雖然有效,但是用兩個(gè)兩路判斷實(shí)現(xiàn)的三路判斷,得到的代碼不反映原始問(wèn)題的真正三路判斷思維。設(shè)想一下,如果我們需要像這樣做一個(gè)五路判斷呢。這個(gè)時(shí)候if-else結(jié)構(gòu)將嵌套四層,Python代碼會(huì)一直寫到屏幕的右邊。(資深程序員會(huì)告訴你,其實(shí)所編寫的程序也是“苗條”的好,因?yàn)椤芭帧绷耍f(shuō)明程序嵌套深,這樣的程序就復(fù)雜了。)3.4.3多重條件分支語(yǔ)句在Python中編寫多路判斷還有另一種方法,它保留了嵌套結(jié)構(gòu)的語(yǔ)義,但看起來(lái)更舒服。這就是將一個(gè)else和一個(gè)if組合成一個(gè)稱為elif的子句(讀作“ell-if”)。if<條件1>:<情況1陳述>elif<條件2>:<情況2陳述>elif<條件3>:<情況3陳述>…else:<缺省陳述>3.4.3多重條件分支語(yǔ)句這個(gè)格式用于分隔任意數(shù)量的互斥代碼塊。Python將依次對(duì)每個(gè)條件求值,尋找第一個(gè)為真的條件。如果找到真條件,就執(zhí)行在該條件下縮進(jìn)的語(yǔ)句,并且控制轉(zhuǎn)到整個(gè)if-elif-else之后的下一語(yǔ)句。如果沒(méi)有條件為真,則執(zhí)行else下的語(yǔ)句。else子句是可選的,如果省略,則可能沒(méi)有語(yǔ)句塊被執(zhí)行。【程序?qū)嵗?-6】二次方程求解程序,用if-elif-else表示三路判斷得到很好的程序。#quadratic4.pyimportmathdefmain():print("該程序找到二次方程的真實(shí)解。\n")a=float(input("輸入系數(shù)a:"))b=float(input("輸入系數(shù)b:"))c=float(input("輸入系數(shù)c:"))discrim=b*b-4*a*c3.4.3多重條件分支語(yǔ)句ifdiscrim<0:print("\n這個(gè)等式?jīng)]有實(shí)根!")elifdiscrim==0:root=-b/(2*a)print("\n有一個(gè)雙根!",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多重條件分支語(yǔ)句3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)由于判斷結(jié)構(gòu)可以改變程序的控制流,因此算法就從單調(diào)、逐步、嚴(yán)格的順序處理中解脫了出來(lái)。下面,我們來(lái)看一個(gè)更復(fù)雜的判斷問(wèn)題設(shè)計(jì),從而展示設(shè)計(jì)過(guò)程中的一些挑戰(zhàn)。假設(shè)我們需要一個(gè)算法,找出三個(gè)數(shù)中最大的一個(gè)。這個(gè)算法可能是一個(gè)更大的問(wèn)題的一部分,例如確定等級(jí)或計(jì)算稅額。也就是說(shuō),計(jì)算機(jī)如何確定用戶的三個(gè)輸入中哪一個(gè)最大?下面是簡(jiǎn)單的程序大綱:defmain():x1,x2,x3=eval(input("請(qǐng)輸入三個(gè)值:"))#填補(bǔ)代碼將maxval設(shè)置為最大值
print("最大的值是",maxval)3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)請(qǐng)注意,這里使用eval來(lái)獲取三個(gè)數(shù),這種方式比較“粗暴”。在程序設(shè)計(jì)實(shí)踐中,通常應(yīng)該避免eval。不過(guò),這里我們只是關(guān)心開(kāi)發(fā)和測(cè)試一些算法思想。在閱讀下面的分析之前,建議你先試著自己解決這個(gè)問(wèn)題。3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)1.策略1:比較每個(gè)值顯然,這個(gè)程序向我們提出了一個(gè)判斷問(wèn)題。我們需要一系列語(yǔ)句,將maxval的值設(shè)置為三個(gè)輸入x1、x2和x3中的最大值。看上去這像是一個(gè)三路判斷。maxval=x1maxval=x2maxval=x33.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)讓我們考慮第一種可能性:x1最大。為了確定x1確實(shí)是最大的,我們只需要檢查它至少與另外兩個(gè)一樣大。下面是第一次嘗試:ifx1>=x2>=x3:maxval=x1Python允許這種復(fù)合條件,也就是說(shuō),當(dāng)x1至少與x2一樣大且x2至少與x3一樣大時(shí),條件為真。條件清楚地表明x1至少與x2和x3一樣大,因此將其值賦給maxval應(yīng)該是正確的(始終要特別注意邊界值)。但是,我們是否能確定當(dāng)x1最大時(shí),在所有情況下這個(gè)條件都是真的呢?假設(shè)實(shí)際值是5、2和4,顯然,x1是最大的,但條件返回false,因?yàn)殛P(guān)系5≥2≥4不成立。3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)要確保x1是最大的,但不關(guān)心x2和x3的相對(duì)順序。我們真正需要的是確定x1>=x2且x1>=x3。Python允許我們測(cè)試這樣的多個(gè)條件,只要用and關(guān)鍵字將它們組合起來(lái):ifx1>=x2andx1>=x3:#x1大于其他每個(gè)
maxval=x1要完成該程序,我們只需要為其他可能性執(zhí)行類似的測(cè)試:ifx1>=x2andx1>=x3:maxval=x1elifx2>=x1andx2>=x3:maxval=x2else:maxval=x33.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)我們的算法基本上是檢查了每個(gè)可能的值,以確定它是否最大。這在只有三個(gè)值時(shí)結(jié)果還是簡(jiǎn)單的,但如果試圖找到五個(gè)值中最大的,解決方案恐怕就復(fù)雜或者說(shuō)啰嗦了。3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)2.策略2:判斷樹(shù)第二種方式是使用“判斷樹(shù)”方法。假設(shè)我們從一個(gè)簡(jiǎn)單的測(cè)試x1>=x2開(kāi)始。如果條件為真,只需要看看x1和x3哪個(gè)更大。如果條件為假,則結(jié)果歸結(jié)為x2和x3之間的選擇。第一個(gè)判斷“分支”有兩種可能性,每種又有另一個(gè)判斷,因此稱為“判斷樹(shù)”。下圖用流程圖展示了這種情況。這個(gè)流程圖很容易轉(zhuǎn)換成嵌套的if-else語(yǔ)句。三者最大問(wèn)題的判斷樹(shù)方法的流程圖ifx1>=x2:ifx1>=x3:maxval=x1else:maxval=x3e1se:ifx2>=x3:maxval=x2e1se:maxval=x33.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)這個(gè)方法的優(yōu)勢(shì)是效率。無(wú)論三個(gè)值的順序如何,該算法都將進(jìn)行兩次比較,并將正確的值分配給maxval,但這種方法的結(jié)構(gòu)比第一種復(fù)雜。3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)3.策略3:順序處理如果面對(duì)一個(gè)包含有幾百個(gè)數(shù)字的集合,又沒(méi)有特定的順序,你將如何找到這個(gè)集合中最大的數(shù)字呢?通常我們會(huì)制定一個(gè)簡(jiǎn)單的策略,即順序?yàn)g覽列表,記錄到目前為止最大的數(shù)字。在程序設(shè)計(jì)中,我們使用變量maxval來(lái)記錄這個(gè)最大值,最后maxval將自動(dòng)包含列表中的最大值,流程圖描述如圖所示。三者最大問(wèn)題的順序方法的流程圖3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)下面是對(duì)應(yīng)的Python代碼:maxval=x1ifx2>maxval:maxval=x2ifx3>maxval:maxva1=x33.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)顯然,順序方法是三種算法中最好的,代碼簡(jiǎn)單,只包含兩個(gè)簡(jiǎn)單的判斷,并且順序處理比以前算法中使用的嵌套更容易理解。此外,這個(gè)思路能很好地?cái)U(kuò)展到更大的問(wèn)題。最后一個(gè)解決方案可以擴(kuò)展到更大的問(wèn)題。我們可以輕松地編寫一個(gè)程序,允許將該算法折疊成一個(gè)循環(huán),找到n個(gè)數(shù)字中最大的。每次取得一個(gè)值,并不斷重復(fù)使用單個(gè)變量x。每次比較最新的x和maxval的當(dāng)前值,看它是否更大。【程序?qū)嵗?-7】查找一系列數(shù)字中的最大值。#maxn.py#查找一系列數(shù)字的最大值defmain():n=int(input("一共有多少個(gè)數(shù)字?"))#將max設(shè)置為第一個(gè)值
maxval=float(input("輸入一個(gè)數(shù)字>>"))3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)#現(xiàn)在比較n-1個(gè)連續(xù)值
foriinrange(n-1):x=float(input("輸入一個(gè)數(shù)字>>"))ifx>maxval:maxval=xprint("這個(gè)最大的值是",maxval)main()3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)這段代碼利用嵌套在循環(huán)中的判斷來(lái)完成工作。在循環(huán)的每次迭代中,將到目前為止看到的最大值存入maxval。3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)4.策略4:使用內(nèi)置函數(shù)Python實(shí)際上有一個(gè)內(nèi)置的返回最大參數(shù)的函數(shù)max,即: defmain(): x1,x2,x3=eval(input("請(qǐng)輸入三個(gè)值:")) print("最大的值是",max(x1,x2,x3))解決這個(gè)問(wèn)題的嘗試展示了算法和程序設(shè)計(jì)中的一些重要思想。3.4.4程序示例:尋找三個(gè)數(shù)中最大的一個(gè)(1)存在多種實(shí)現(xiàn)方式。任何有價(jià)值的計(jì)算問(wèn)題,都有多種解決方法。因此,不要急于編寫。想想你的設(shè)計(jì),問(wèn)自己是否存在更好的方法來(lái)處理這個(gè)問(wèn)題。重要的是要找到一個(gè)正確的算法,力求清晰、簡(jiǎn)單、高效、可擴(kuò)展和優(yōu)雅,一些直接的方法通常簡(jiǎn)單、清楚、有效。(2)通用性好。通過(guò)考慮更通用的n個(gè)數(shù)的最大值問(wèn)題,得到最佳解決方案。(3)不要重新發(fā)明輪子。第四個(gè)解決
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年神經(jīng)系統(tǒng)技能競(jìng)賽試題
- 2025資產(chǎn)管理委托貸款合同模板
- 綜合解析2025年MySQL考試試題及答案
- 2025員工福利集體合同(樣本)
- 2025醫(yī)療設(shè)備采購(gòu)合同
- 財(cái)務(wù)成本管理考試中的邏輯陷阱試題及答案
- 高效編程實(shí)踐試題及答案
- 計(jì)算機(jī)二級(jí)MySQL查詢性能優(yōu)化試題及答案
- 網(wǎng)絡(luò)管理員考試復(fù)習(xí)指南與試題及答案
- 現(xiàn)代主義與后現(xiàn)代主義文學(xué)概論試題及答案
- 麻醉科醫(yī)師晉升副主任醫(yī)師病例分析專題報(bào)告三篇
- HG∕T 3714-2014 耐油輸送帶 國(guó)標(biāo)
- 2024年湖南省高中學(xué)業(yè)水平合格性考試英語(yǔ)試卷真題(含答案詳解)
- 《內(nèi)科胸腔鏡術(shù)》課件
- CJJ 33-2005城鎮(zhèn)燃?xì)廨斉涔こ淌┕づc驗(yàn)收規(guī)范
- 《市場(chǎng)營(yíng)銷:網(wǎng)絡(luò)時(shí)代的超越競(jìng)爭(zhēng)》第4版 課件 第9章 通過(guò)構(gòu)建渠道網(wǎng)絡(luò)傳遞顧客價(jià)值
- 農(nóng)民工工資代付款方協(xié)議模板
- 中醫(yī)醫(yī)療技術(shù)手冊(cè)2013普及版
- 藥物合成反應(yīng)-9合成設(shè)計(jì)原理
- 跨學(xué)科閱讀綱要智慧樹(shù)知到期末考試答案章節(jié)答案2024年山東師范大學(xué)
- 2025屆湖南省數(shù)學(xué)高一下期末學(xué)業(yè)水平測(cè)試試題含解析
評(píng)論
0/150
提交評(píng)論