人工智能技術(shù)基礎(chǔ) 課件 模塊5、6 流程控制、函數(shù)_第1頁
人工智能技術(shù)基礎(chǔ) 課件 模塊5、6 流程控制、函數(shù)_第2頁
人工智能技術(shù)基礎(chǔ) 課件 模塊5、6 流程控制、函數(shù)_第3頁
人工智能技術(shù)基礎(chǔ) 課件 模塊5、6 流程控制、函數(shù)_第4頁
人工智能技術(shù)基礎(chǔ) 課件 模塊5、6 流程控制、函數(shù)_第5頁
已閱讀5頁,還剩162頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

5.1條件表達(dá)式算術(shù)運(yùn)算符:+、-、*、/、//、%、**關(guān)系運(yùn)算符:>、<、==、<=、>=、!=,可以連續(xù)使用,如>>>1<2<3True>>>1<2>3False>>>1<3>2True測試運(yùn)算符:in、notin、is、isnot邏輯運(yùn)算符:and、or、not,注意短路求值位運(yùn)算符:~、&、|、^、<<、>>矩陣乘法運(yùn)算符:@5.1條件表達(dá)式在選擇和循環(huán)結(jié)構(gòu)中,條件表達(dá)式的值只要不是False、0(或0.0、0j等)、空值None、空列表、空元組、空集合、空字典、空字符串、空range對象或其他空迭代對象,Python解釋器均認(rèn)為與True等價。從這個意義上來講,幾乎所有的Python合法表達(dá)式都可以作為條件表達(dá)式,包括含有函數(shù)調(diào)用的表達(dá)式。5.1條件表達(dá)式>>>if3:#使用整數(shù)作為條件表達(dá)式

print(5)5>>>a=[1,2,3]>>>ifa:#使用列表作為條件表達(dá)式

print(a) [1,2,3]>>>a=[]>>>ifa: print(a)else:print('empty')empty5.1條件表達(dá)式>>>i=s=0>>>whilei<=10:#使用關(guān)系表達(dá)式作為條件表達(dá)式

s+=ii+=1>>>print(s)55>>>i=s=0>>>whileTrue:#使用常量True作為條件表達(dá)式

s+=ii+=1ifi>10: break>>>print(s)55>>>s=0>>>foriinrange(0,11,1):#遍歷迭代對象中的所有元素s+=i>>>print(s)55邏輯運(yùn)算符and和or以及關(guān)系運(yùn)算符具有惰性求值特點(diǎn)LK2K1K1K2KLL(1)or,并聯(lián)電路(2)and,串聯(lián)電路(3)not,短路5.1條件表達(dá)式5.1條件表達(dá)式關(guān)系運(yùn)算符也具有短路求值或惰性求值的特點(diǎn),只計(jì)算必須計(jì)算的表達(dá)式的值。以“and”為例,對于表達(dá)式“表達(dá)式1and表達(dá)式2”而言,如果“表達(dá)式1”的值為“False”或其他等價值時,不論“表達(dá)式2”的值是什么,整個表達(dá)式的值都是“False”,此時“表達(dá)式2”的值無論是什么都不影響整個表達(dá)式的值,因此將不會被計(jì)算,從而減少不必要的計(jì)算和判斷。5.1條件表達(dá)式在設(shè)計(jì)條件表達(dá)式時,如果能夠大概預(yù)測不同條件失敗的概率,并將多個條件根據(jù)“and”和“or”運(yùn)算的短路求值特性來組織先后順序,可以大幅度提高程序運(yùn)行效率。>>>defJoin(chList,sep=None):

return(sepor',').join(chList)>>>chTest=['1','2','3','4','5']>>>Join(chTest)'1,2,3,4,5'>>>Join(chTest,':')'1:2:3:4:5'>>>Join(chTest,'')'12345'5.1條件表達(dá)式在Python中,條件表達(dá)式中不允許使用賦值運(yùn)算符“=”。>>>ifa=3:SyntaxError:invalidsyntax>>>if(a=3)and(b=4): SyntaxError:invalidsyntax5.2.1單分支選擇結(jié)構(gòu)if表達(dá)式:

語句塊x=input('Inputtwonumber:')a,b=map(int,x.split())ifa>b:a,b=b,a#序列解包,交換兩個變量的值print(a,b)5.2.2雙分支結(jié)構(gòu)if表達(dá)式:

語句塊1else:

語句塊2>>>chTest=['1','2','3','4','5']>>>ifchTest: print(chTest)else: print('Empty')['1','2','3','4','5']5.2.2雙分支結(jié)構(gòu)Python還支持如下形式的表達(dá)式:value1ifconditionelsevalue2當(dāng)條件表達(dá)式condition的值與True等價時,表達(dá)式的值為value1,否則表達(dá)式的值為value2。另外,在value1和value2中還可以使用復(fù)雜表達(dá)式,包括函數(shù)調(diào)用和基本輸出語句。這個結(jié)構(gòu)的表達(dá)式也具有惰性求值的特點(diǎn)。>>>a=5>>>print(6)ifa>3elseprint(5)6>>>print(6ifa>3else5)6>>>b=6ifa>13else9>>>b95.2.2雙分支結(jié)構(gòu)#此時還沒有導(dǎo)入math模塊>>>x=math.sqrt(9)if5>3elserandom.randint(1,100)NameError:name'math'isnotdefined>>>importmath#此時還沒有導(dǎo)入random模塊,但由于條件表達(dá)式5>3的值為True,所以可以正常運(yùn)行>>>x=math.sqrt(9)if5>3elserandom.randint(1,100)#此時還沒有導(dǎo)入random模塊,由于條件表達(dá)式2>3的值為False,需要計(jì)算第二個表達(dá)式的值,因此出錯>>>x=math.sqrt(9)if2>3elserandom.randint(1,100)NameError:name'random'isnotdefined>>>importrandom>>>x=math.sqrt(9)if2>3elserandom.randint(1,100)5.2.3多分支結(jié)構(gòu)if表達(dá)式1:

語句塊1elif表達(dá)式2:

語句塊2elif表達(dá)式3:

語句塊3else:

語句塊4其中,關(guān)鍵字elif是elseif的縮寫。5.2.3多分支結(jié)構(gòu)利用多分支選擇結(jié)構(gòu)將成績從百分制變換到等級制。deffunc(score): ifscore>100: return'wrongscore.must<=100.' elifscore>=90: return'A'elifscore>=80: return'B'elifscore>=70: return'C'elifscore>=60: return'D'elifscore>=0: return'E'else: return'wrongscore.must>0' 5.2.4選擇結(jié)構(gòu)的嵌套if表達(dá)式1:語句塊1if表達(dá)式2:語句塊2else:語句塊3else:if表達(dá)式4:語句塊4注意:縮進(jìn)必須要正確并且一致。5.2.4選擇結(jié)構(gòu)的嵌套使用嵌套的選擇結(jié)構(gòu)實(shí)現(xiàn)百分制成績到等級制的轉(zhuǎn)換。>>>deffunc(score): degree='DCBAAE' ifscore>100orscore<0:return'wrongscore.mustbetween0and100.'else:index=(score-60)//10ifindex>=0:returndegree[index]else: returndegree[-1]5.2.5構(gòu)建跳轉(zhuǎn)表實(shí)現(xiàn)多分支選擇結(jié)構(gòu)使用列表、元組或字典可以很容易構(gòu)建跳轉(zhuǎn)表,在某些場合下可以更快速地實(shí)現(xiàn)類似于多分支選擇結(jié)構(gòu)的功能。funcDict={'1':lambda:print('Youinput1'),'2':lambda:print('Youinput2'),'3':lambda:print('Youinput3')}x=input('Inputanintegertocalldifferentfunction:')func=funcDict.get(x,None)iffunc:func()else:print('Wronginteger.')5.2.5選擇結(jié)構(gòu)應(yīng)用例3-1:面試資格確認(rèn)。age=24subject="計(jì)算機(jī)"college="非重點(diǎn)"if(age>25andsubject=="電子信息工程")or\(college=="重點(diǎn)"andsubject=="電子信息工程")or\(age<=28andsubject=="計(jì)算機(jī)"):print("恭喜,你已獲得我公司的面試機(jī)會!")else:print("抱歉,你未達(dá)到面試要求")5.2.5選擇結(jié)構(gòu)應(yīng)用例3-2:用戶輸入若干個分?jǐn)?shù),求所有分?jǐn)?shù)的平均分。每輸入一個分?jǐn)?shù)后詢問是否繼續(xù)輸入下一個分?jǐn)?shù),回答“yes”就繼續(xù)輸入下一個分?jǐn)?shù),回答“no”就停止輸入分?jǐn)?shù)。5.2.5選擇結(jié)構(gòu)應(yīng)用numbers=[]#使用列表存放臨時數(shù)據(jù)whileTrue:x=input('請輸入一個成績:')try:#異常處理結(jié)構(gòu)numbers.append(float(x))except:print('不是合法成績')whileTrue:flag=input('繼續(xù)輸入嗎?(yes/no)').lower()ifflagnotin('yes','no'):#限定用戶輸入內(nèi)容必須為yes或noprint('只能輸入yes或no')else:breakifflag=='no':breakprint(sum(numbers)/len(numbers))5.2.5選擇結(jié)構(gòu)應(yīng)用例3-3:編寫程序,判斷今天是今年的第幾天。importtimedate=time.localtime()#獲取當(dāng)前日期時間year,month,day=date[:3]day_month=[31,28,31,30,31,30,31,31,30,31,30,31]ifyear%400==0or(year%4==0andyear%100!=0):#判斷是否為閏年day_month[1]=29ifmonth==1:print(day)else:print(sum(day_month[:month-1])+day)5.2.5選擇結(jié)構(gòu)應(yīng)用其中閏年判斷可以直接使用calendar模塊的方法。>>>calendar.isleap(2016)True>>>calendar.isleap(2015)False5.2.5選擇結(jié)構(gòu)應(yīng)用或者使用下面的方法直接計(jì)算今天是今年的第幾天>>>datetime.date.today().timetuple().tm_yday208>>>datetime.date(2015,7,25).timetuple().tm_yday2065.2.5選擇結(jié)構(gòu)應(yīng)用也可以使用datetime模塊提供的功能來計(jì)算>>>today=datetime.date.today()>>>todaydatetime.date(2015,7,27)>>>firstDay=datetime.date(today.year,1,1)>>>firstDaydatetime.date(2015,1,1)>>>daysDelta=today-firstDay+datetime.timedelta(days=1)>>>daysDelta.days2085.2.5選擇結(jié)構(gòu)應(yīng)用datetime還提供了其他功能>>>now=datetime.datetime.now()>>>nowdatetime.datetime(2015,12,6,16,1,6,313898)>>>now.replace(second=30)#替換日期時間中的秒datetime.datetime(2015,12,6,16,1,30,313898)>>>now+datetime.timedelta(days=5)#計(jì)算5天后的日期時間datetime.datetime(2015,12,11,16,1,6,313898)>>>now+datetime.timedelta(weeks=-5)#計(jì)算5周前的日期時間datetime.datetime(2015,11,1,16,1,6,313898)計(jì)算兩個日期之間相差多少天。defdaysBetween(year1,month1,day1,year2,month2,day2):fromdatetimeimportdatedif=date(year1,month1,day1)dif=dif-date(year2,month2,day2)returndif.daysprint(daysBetween(2016,12,11,2016,11,27))print(daysBetween(2016,12,11,2011,11,27))5.2.5選擇結(jié)構(gòu)應(yīng)用5.3.1for循環(huán)與while循環(huán)Python提供了兩種基本的循環(huán)結(jié)構(gòu)語句——while和for。while循環(huán)一般用于循環(huán)次數(shù)難以提前確定的情況,也可以用于循環(huán)次數(shù)確定的情況。for循環(huán)一般用于循環(huán)次數(shù)可以提前確定的情況,尤其是用于枚舉序列或迭代對象中的元素。一般優(yōu)先考慮使用for循環(huán)。相同或不同的循環(huán)結(jié)構(gòu)之間都可以互相嵌套,實(shí)現(xiàn)更為復(fù)雜的邏輯。5.3.1for循環(huán)與while循環(huán)while條件表達(dá)式: 循環(huán)體[else:#如果循環(huán)是因?yàn)閎reak結(jié)束的,就不執(zhí)行else中的代碼 else子句代碼塊]for取值in序列或迭代對象: 循環(huán)體[else:else子句代碼塊]5.3.2循環(huán)結(jié)構(gòu)的優(yōu)化為了優(yōu)化程序以獲得更高的效率和運(yùn)行速度,在編寫循環(huán)語句時,應(yīng)盡量減少循環(huán)內(nèi)部不必要的計(jì)算,將與循環(huán)變量無關(guān)的代碼盡可能地提取到循環(huán)之外。對于使用多重循環(huán)嵌套的情況,應(yīng)盡量減少內(nèi)層循環(huán)中不必要的計(jì)算,盡可能地向外提。5.3.2循環(huán)結(jié)構(gòu)的優(yōu)化優(yōu)化前的代碼:digits=(1,2,3,4)foriinrange(1000):result=[]foriindigits:forjindigits:forkindigits:result.append(i*100+j*10+k)5.3.2循環(huán)結(jié)構(gòu)的優(yōu)化優(yōu)化后的代碼:foriinrange(1000):result=[]foriindigits:i=i*100forjindigits:j=j*10forkindigits:result.append(i+j+k)5.3.2循環(huán)結(jié)構(gòu)的優(yōu)化在循環(huán)中應(yīng)盡量引用局部變量,因?yàn)榫植孔兞康牟樵兒驮L問速度比全局變量略塊。另外,在使用模塊中的方法時,可以通過將其直接導(dǎo)入來減少查詢次數(shù)和提高運(yùn)行速度。importtimeimportmathstart=time.time()#獲取當(dāng)前時間foriinrange(10000000):math.sin(i)print('TimeUsed:',time.time()-start)#輸出所用時間loc_sin=math.sinstart=time.time()foriinrange(10000000):loc_sin(i)print('TimeUsed:',time.time()-start)5.4break和continue語句break語句在while循環(huán)和for循環(huán)中都可以使用,一般放在if選擇結(jié)構(gòu)中,一旦break語句被執(zhí)行,將使得整個循環(huán)提前結(jié)束。continue語句的作用是終止當(dāng)前循環(huán),并忽略continue之后的語句,然后回到循環(huán)的頂端,提前進(jìn)入下一次循環(huán)。除非break語句讓代碼更簡單或更清晰,否則不要輕易使用。5.4break和continue語句下面的代碼用來計(jì)算小于100的最大素?cái)?shù),注意break語句和else子句的用法。>>>forninrange(100,1,-1):foriinrange(2,n): ifn%i==0: breakelse: print(n) break 975.4break和continue語句刪除上面代碼中最后一個break語句,則可以用來輸出100以內(nèi)的所有素?cái)?shù)。>>>forninrange(100,1,-1):foriinrange(2,n): ifn%i==0: breakelse: print(n,end='')97898379737167615953474341373129231917131175325.4break和continue語句警惕continue可能帶來的問題:>>>i=0>>>whilei<10: ifi%2==0: continue print(i) i+=1永不結(jié)束的死循環(huán),Ctrl+C強(qiáng)行終止。5.4break和continue語句這樣子就不會有問題>>>foriinrange(10): ifi%2==0: continue print(i,end='')135795.4break和continue語句>>>foriinrange(10): ifi%2==0: i+=1#沒有用呀?jīng)]有用 continue print(i,end='')135795.4break和continue語句每次進(jìn)入循環(huán)時的i已經(jīng)不再是上一次的i,所以修改其值并不會影響循環(huán)的執(zhí)行。>>>foriinrange(7): print(id(i),':',i)10416692:010416680:110416668:210416656:310416644:410416632:510416620:65.5案例精選例5-4:計(jì)算1+2+3+…+100的值。s=0foriinrange(1,101):s=s+iprint('1+2+3+…+100=',s)print('1+2+3+…+100=',sum(range(1,101)))5.5案例精選例5-5:輸出序列中的元素。a_list=['a','b','mpilgrim','z','example']fori,vinenumerate(a_list):print('列表的第',i+1,'個元素是:',v)5.5案例精選例5-6:求1~100之間能被7整除,但不能同時被5整除的所有整數(shù)。foriinrange(1,101): ifi%7==0andi%5!=0: print(i)5.5案例精選例5-7:輸出“水仙花數(shù)”。所謂水仙花數(shù)是指1個3位的十進(jìn)制數(shù),其各位數(shù)字的立方和等于該數(shù)本身。例如:153是水仙花數(shù),因?yàn)?53=13+53+33。#傳統(tǒng)套路foriinrange(100,1000):#這里是序列解包的用法bai,shi,ge=map(int,str(i))ifge**3+shi**3+bai**3==i:print(i)5.5案例精選#函數(shù)式編程fornuminrange(100,1000):r=map(lambdax:int(x)**3,str(num))ifsum(r)==num:print(num)5.5案例精選例5-8:求平均分。score=[70,90,78,85,97,94,65,80]s=0foriinscore: s+=iprint(s/len(score))print(sum(score)/len(score))#更建議直接這樣做5.5案例精選例5-9:打印九九乘法表。foriinrange(1,10):forjinrange(1,i+1):print('{0}*{1}={2}'.format(i,j,i*j).ljust(6),end='')print()5.5案例精選例5-10:求200以內(nèi)能被17整除的最大正整數(shù)。foriinrange(200,0,-1): ifi%17==0: print(i) break5.5案例精選例5-11:判斷一個數(shù)是否為素?cái)?shù)。importmathn=input('Inputaninteger:')n=int(n)m=math.ceil(math.sqrt(n)+1)foriinrange(2,m):ifn%i==0andi<n:print('No')breakelse:print('Yes')5.5案例精選例5-12:雞兔同籠問題。假設(shè)共有雞、兔30只,腳90只,求雞、兔各有多少只。forjiinrange(0,31):if2*ji+(30-ji)*4==90:print('ji:',ji,'tu:',30-ji)5.5案例精選另一種計(jì)算方法>>>defdemo(tui,jitu):tu=(tui-jitu*2)/2ifint(tu)==tu:return(int(tu),int(jitu-tu))else:return'DataError' >>>demo(90,30)(15,15)>>>demo(90,31)(14,17)>>>demo(91,30)'DataError'5.5案例精選例5-13:編寫程序,輸出由1、2、3、4這四個數(shù)字組成的每位數(shù)都不相同的所有三位數(shù)。digits=(1,2,3,4)foriindigits:forjindigits:forkindigits:ifi!=jandj!=kandi!=k:print(i*100+j*10+k)3.5案例精選從代碼優(yōu)化的角度來講,上面這段代碼并不是很好,其中有些判斷完全可以在外層循環(huán)來做,從而提高運(yùn)行效率。digits=(1,2,3,4)foriindigits:forjindigits:ifj==i:continueforkindigits:ifk==iork==j:continueprint(i*100+j*10+k)5.5案例精選當(dāng)然,還可以進(jìn)一步優(yōu)化。defdemo1(data,k=3):assertk==3,'kmustbe3'foriindata:ifi==0:continueii=i*100forjindata:ifj==i:continuejj=j*10forkindata:ifk!=iandk!=j:print(ii+jj+k)5.5案例精選使用集合實(shí)現(xiàn)同樣功能。defdemo2(data,k=3):data=set(data)foriindata:ifi==0:continueii=i*100forjindata-{i}:jj=j*10forkindata-{i,j}:print(ii+jj+k)5.5案例精選例5-14:編寫程序,生成一個含有20個隨機(jī)數(shù)的列表,要求所有元素不相同,并且每個元素的值介于1到100之間。importrandomx=[]whileTrue:iflen(x)==20:breakn=random.randint(1,100)ifnnotinx:x.append(n)print(x)print(len(x))print(sorted(x))5.5案例精選如果用集合來做,會更簡單一些。fromrandomimportrandintx=set()whilelen(x)<20:x.add(randint(1,100))print(x)print(sorted(x))5.5案例精選例5-15編寫程序,計(jì)算組合數(shù)C(n,i),即從n個元素中任選i個,有多少種選法。根據(jù)組合數(shù)定義,需要計(jì)算3個數(shù)的階乘,在很多編程語言中都很難直接使用整型變量表示大數(shù)的階乘結(jié)果,雖然Python并不存在這個問題,但是計(jì)算大數(shù)的階乘仍需要相當(dāng)多的時間。本例提供另一種計(jì)算方法:以Cni(8,3)為例,按定義式展開如下,對于(5,8]區(qū)間的數(shù),分子上出現(xiàn)一次而分母上沒出現(xiàn);(3,5]區(qū)間的數(shù)在分子、分母上各出現(xiàn)一次;[1,3]區(qū)間的數(shù)分子上出現(xiàn)一次而分母上出現(xiàn)兩次。5.5案例精選defCni1(n,i):ifnot(isinstance(n,int)andisinstance(i,int)andn>=i):print('nandimustbeintegersandn>=i.')returnresult=1Min,Max=sorted((i,n-i))foriinrange(n,0,-1):ifi>Max:result*=ielifi<=Min:result/=ireturnresult下面的代碼與剛才的代碼相比,效率有提高嗎?defcni2(n,i):minNI=min(i,n-i)result=1forjinrange(0,minNI):result=result*(n-j)//(j+1)returnresult5.5案例精選下面的代碼有錯誤嗎?defcni2(n,i):minNI=min(i,n-i)result=1forjinrange(0,minNI):result=result*(n-j)//(minNI-j)returnresult5.5案例精選3.5案例精選也可以使用math庫中的階乘函數(shù)直接按組合數(shù)定義實(shí)現(xiàn)。>>>defCni2(n,i):importmathreturnint(math.factorial(n)/math.factorial(i)/math.factorial(n-i))>>>Cni2(6,2)15還可以直接使用Python標(biāo)準(zhǔn)庫itertools提供的函數(shù)。>>>importitertools>>>len(tuple(binations(range(60),2)))17705.5案例精選itertools還提供了排列函數(shù)permutations()。>>>importitertools>>>foriteminitertools.permutations(range(1,4),2):print(item)

(1,2)(1,3)(2,1)(2,3)(3,1)(3,2)5.5案例精選itertools還提供了用于循環(huán)遍歷可迭代對象元素的函數(shù)cycle()。>>>importitertools>>>x='PrivateKey'>>>y=itertools.cycle(x)#循環(huán)遍歷序列中的元素>>>foriinrange(20):print(next(y),end=',') P,r,i,v,a,t,e,,K,e,y,P,r,i,v,a,t,e,,K,>>>foriinrange(5):print(next(y),end=',') e,y,P,r,i,5.5案例精選itertools還提供了根據(jù)一個序列的值對另一個序列進(jìn)行過濾的函數(shù)compress()。>>>x=range(1,20)>>>y=(1,0)*9+(1,)>>>y(1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1)>>>list(press(x,y))[1,3,5,7,9,11,13,15,17,19]5.5案例精選itertools還提供了根據(jù)函數(shù)返回值對序列進(jìn)行分組的函數(shù)groupby()。>>>defgroup(v):

ifv>10:

return'greaterthan10'

elifv<5:

return'lessthan5'

else:

return'between5and10'>>>x=range(20)>>>y=itertools.groupby(x,group)#根據(jù)函數(shù)返回值對序列元素進(jìn)行分組>>>fork,viny:

print(k,':',list(v))lessthan5:[0,1,2,3,4]between5and10:[5,6,7,8,9,10]greaterthan10:[11,12,13,14,15,16,17,18,19]5.5案例精選例5-16編寫程序,計(jì)算理財(cái)產(chǎn)品收益,假設(shè)收益和本金一起滾動。deflicai(base,rate,days):#初始投資金額

result=base#整除,用來計(jì)算一年可以滾動多少期

times=365//days

foriinrange(times):

result=result+result*rate/365*days

returnresult#14天理財(cái),利率0.0385,投資10萬print(licai(100000,0.0385,14))5.5案例精選例5-17編寫代碼實(shí)現(xiàn)冒泡法排序。fromrandomimportrandintdefbubbleSort(lst):length=len(lst)foriinrange(0,length):forjinrange(0,length-i-1):#比較相鄰兩個元素大小,并根據(jù)需要進(jìn)行交換iflst[j]>lst[j+1]:lst[j],lst[j+1]=lst[j+1],lst[j]lst=[randint(1,100)foriinrange(20)]print('Beforesorted:\n',lst)bubbleSort(lst)print('Aftersorted:\n',lst)5.5案例精選例5-18編寫代碼實(shí)現(xiàn)選擇法排序。defselectSort(lst,reverse=False):length=len(lst)foriinrange(0,length):m=i#假設(shè)剩余元素中第一個最小或最大forjinrange(i+1,length):#掃描剩余元素#如果有更小或更大的,就記錄下它的位置exp='lst[j]<lst[m]'ifreverse:exp='lst[j]>lst[m]'#內(nèi)置函數(shù)eval()用來對字符串進(jìn)行求值ifeval(exp):m=jifm!=i:#如果發(fā)現(xiàn)更小或更大的,就交換值lst[i],lst[m]=lst[m],lst[i]5.5案例精選例5-19二分法查找。二分法查找算法非常適合在大量元素中查找指定的元素,要求序列已經(jīng)排好序(這里假設(shè)按從小到大排序),首先測試中間位置上的元素是否為想查找的元素,如果是則結(jié)束算法;如果序列中間位置上的元素比要查找的元素小,則在序列的后面一半元素中繼續(xù)查找;如果中間位置上的元素比要查找的元素大,則在序列的前面一半元素中繼續(xù)查找。重復(fù)上面的過程,不斷地縮小搜索范圍,直到查找成功或者失?。ㄒ檎业脑夭辉谛蛄兄校?。5.5案例精選defbinarySearch(lst,value):start=0end=len(lst)whilestart<=end:#計(jì)算中間位置middle=(start+end)//2#查找成功,返回元素對應(yīng)的位置ifvalue==lst[middle]:returnmiddle#在后面一半元素中繼續(xù)查找elifvalue>lst[middle]:start=middle+1#在前面一半元素中繼續(xù)查找elifvalue<lst[middle]:end=middle-1#查找不成功,返回FalsereturnFalse5.5案例精選fromrandomimportrandintlst=[randint(1,50)foriinrange(20)]lst.sort()print(lst)result=binarySearch(lst,30)ifresult!=False:print('Success,itspositionis:',result)else:print('Fail.Notexist.')例5-20編寫程序,計(jì)算百錢買百雞問題。假設(shè)公雞5元一只,母雞3元一只,小雞1元三只,現(xiàn)在有100塊錢,想買100只雞,問有多少種買法?#假設(shè)能買x只公雞,x最大為20forxinrange(21):#假設(shè)能買y只母雞,y最大為33foryinrange(34):#假設(shè)能買z只小雞z=100-x-yifz%3==0and5*x+3*y+z//3==100:print(x,y,z)5.5案例精選例5-21編寫代碼,模擬決賽現(xiàn)場最終成績的計(jì)算過程。#這個循環(huán)用來保證必須輸入大于2的整數(shù)作為評委人數(shù)whileTrue:try:n=int(input('請輸入評委人數(shù):'))ifn<=2:print('評委人數(shù)太少,必須多于2個人。')else:#如果輸入大于2的整數(shù),就結(jié)束循環(huán)breakexcept:pass#用來保存所有評委的打分scores=[]5.5案例精選foriinrange(n):#這個while循環(huán)用來保證用戶必須輸入0到100之間的數(shù)字whileTrue:try:score=input('請輸入第{0}個評委的分?jǐn)?shù):'.format(i+1))#把字符串轉(zhuǎn)換為實(shí)數(shù)score=float(score)#用來保證輸入的數(shù)字在0到100之間assert0<=score<=100scores.append(score)#如果數(shù)據(jù)合法,跳出while循環(huán),繼續(xù)輸入下一個評委的得分breakexcept:print('分?jǐn)?shù)錯誤')5.5案例精選#計(jì)算并刪除最高分與最低分highest=max(scores)lowest=min(scores)scores.remove(highest)scores.remove(lowest)#計(jì)算平均分,保留2位小數(shù)finalScore=round(sum(scores)/len(scores),2)formatter='去掉一個最高分{0}\n去掉一個最低分{1}\n最后得分{2}'print(formatter.format(highest,lowest,finalScore))5.5案例精選例5-22遞歸算法求解漢諾塔問題。據(jù)說古代有一個梵塔,塔內(nèi)有三個底座A、B、C,A座上有64個盤子,盤子大小不等,大的在下,小的在上。有一個和尚想把這64個盤子從A座移到C座,但每次只能允許移動一個盤子。在移動盤子的過程中可以利用B座,但任何時刻3個座上的盤子都必須始終保持大盤在下、小盤在上的順序。如果只有一個盤子,則不需要利用B座,直接將盤子從A移動到C即可。和尚想知道這項(xiàng)任務(wù)的詳細(xì)移動步驟和順序。根據(jù)數(shù)學(xué)知識我們可以知道,移動n個盤子需要2^n-1步,64個盤子需要18446744073709551615步。如果每步需要一秒鐘的話,那么就需要584942417355.072年。5.5案例精選defhannoi(num,src,dst,temp=None):globaltimes#聲明用來記錄移動次數(shù)的變量為全局變量asserttype(num)==int,'nummustbeinteger'#確認(rèn)參數(shù)類型和范圍assertnum>0,'nummust>0'ifnum==1:#只剩最后或只有一個盤子需要移動,這也是函數(shù)遞歸調(diào)用的結(jié)束條件print('The{0}Timesmove:{1}==>{2}'.format(times,src,dst))times+=1else:#遞歸調(diào)用函數(shù)自身,先把除最后一個盤子之外的所有盤子移動到臨時柱子上hannoi(num-1,src,temp,dst)hannoi(1,src,dst)#把最后一個盤子直接移動到目標(biāo)柱子上#把除最后一個盤子之外的其他盤子從臨時柱子上移動到目標(biāo)柱子上hannoi(num-1,temp,dst,src)times=1#用來記錄移動次數(shù)的變量hannoi(3,'A','C','B')#A表示最初放置盤子的柱子,C是目標(biāo)柱子,B是臨時柱子5.5案例精選例5-23遞歸算法計(jì)算組合數(shù)。defcni(n,i):ifn==iori==0:return1returncni(n-1,i)+cni(n-1,i-1)print(cni(5,5))5.5案例精選讓你的程序飛起來,提速上萬倍fromfunctoolsimportlru_cache@lru_cache(maxsize=64)defcni(n,i):ifn==iori==0:return1returncni(n-1,i)+cni(n-1,i-1)5.5案例精選例5-24編寫程序,輸出星號組成的菱形。defmain(n):foriinrange(n):print(('*'*i).center(n*3))foriinrange(n,0,-1):print(('*'*i).center(n*3))5.5案例精選例5-25編寫程序,實(shí)現(xiàn)十進(jìn)制整數(shù)到其他任意進(jìn)制的轉(zhuǎn)換。編程要點(diǎn):除基取余,逆序排列5.5案例精選defint2base(n,base):'''把十進(jìn)制整數(shù)n轉(zhuǎn)換成base進(jìn)制'''result=[]div=n#除基取余,逆序排列whilediv!=0:div,mod=divmod(div,base)result.append(mod)result.reverse()result=''.join(map(str,result))#變成數(shù)字,返回returneval(result)5.5案例精選例5-26假設(shè)一列表中包含若干整數(shù),要求將其分成n個子列表,并使得各個子列表中的元素之和盡可能接近。code\numberSplit.py5.5案例精選例5-27每天固定時間定時自動執(zhí)行特定任務(wù)。5.5案例精選importdatetimeimporttimedefdoSth():print('test')#假裝做這件事情需要一分鐘time.sleep(60)5.5案例精選defmain(h=0,m=0):'''h表示設(shè)定的小時,m為設(shè)定的分鐘'''whileTrue:#判斷是否達(dá)到設(shè)定時間,例如0:00whileTrue:now=datetime.datetime.now()#到達(dá)設(shè)定時間,結(jié)束內(nèi)循環(huán)ifnow.hour==handnow.minute==m:break#不到時間就等20秒之后再次檢測time.sleep(20)#做正事,一天做一次doSth()main(10,14)5.5案例精選例5-28給定一個包含若干數(shù)字的序列A(本文以列表為例),求滿足0≤a≤b<n的A[b]-A[a]的最大值。5.5案例精選fromrandomimportrandrange#簡單粗暴的循環(huán)嵌套defmaxDifference1(lst):#負(fù)無窮大diff=-float('inf')forindex,valueinenumerate(lst[:-1]):forvinlst[index+1:]:t=v-valueift>diff:result=(value,v)diff=treturnresult5.5案例精選#高大上的動態(tài)規(guī)劃算法defmaxDifference2(lst):diff=-float('inf')

minCurrent=lst[0]

forvalueinlst[1:]:ifvalue<minCurrent:minCurrent=valueelse:t=value-minCurrentift>diff:diff=tresult=(minCurrent,value)returnresult5.5案例精選例5-29計(jì)算前n個自然數(shù)的階乘之和1!+2!+3!+...+n!的值。deffactorialBefore(n):result,t=1,1foriinrange(2,n+1):t*=iresult+=treturnresult或者下面的方法(不過效率會低一些):>>>frommathimportfactorial>>>sum(map(factorial,range(1,100)))9427862397658265791605952682068393813547543496010509743453954104070782302495904144588301174426181807329112035202088893716416591213565564423365289204209403135.5案例精選將可能需要反復(fù)執(zhí)行的代碼封裝為函數(shù),并在需要該功能的地方進(jìn)行調(diào)用,不僅可以實(shí)現(xiàn)代碼復(fù)用,更重要的是可以保證代碼的一致性,只需要修改該函數(shù)代碼則所有調(diào)用均受到影響。設(shè)計(jì)函數(shù)時,應(yīng)注意提高模塊的內(nèi)聚性,同時降低模塊之間的隱式耦合。在實(shí)際項(xiàng)目開發(fā)中,往往會把一些通用的函數(shù)封裝到一個模塊中,并把這個通用模塊文件放到頂層文件夾中,這樣更方便管理。6.1函數(shù)定義在編寫函數(shù)時,應(yīng)盡量減少副作用,盡量不要修改參數(shù)本身,不要修改除返回值以外的其他內(nèi)容。應(yīng)充分利用Python函數(shù)式編程的特點(diǎn),讓自己定義的函數(shù)盡量符合純函數(shù)式編程的要求,例如保證線程安全、可以并行運(yùn)行等等。6.1函數(shù)定義6.1函數(shù)定義函數(shù)定義語法:def函數(shù)名([參數(shù)列表]):'''注釋'''

函數(shù)體注意事項(xiàng)函數(shù)形參不需要聲明其類型,也不需要指定函數(shù)返回值類型即使該函數(shù)不需要接收任何參數(shù),也必須保留一對空的圓括號括號后面的冒號必不可少函數(shù)體相對于def關(guān)鍵字必須保持一定的空格縮進(jìn)Python允許嵌套定義函數(shù)6.1函數(shù)定義生成斐波那契數(shù)列的函數(shù)定義和調(diào)用deffib(n):a,b=0,1whilea<n:print(a,end='')a,b=b,a+bprint()fib(1000)6.1函數(shù)定義在定義函數(shù)時,開頭部分的注釋并不是必需的,但是如果為函數(shù)的定義加上這段注釋的話,可以為用戶提供友好的提示和使用幫助。Python是一種高級動態(tài)編程語言,變量類型是隨時可以改變的。Python中的函數(shù)和自定義對象的成員也是可以隨時發(fā)生改變的,可以為函數(shù)和自定義對象動態(tài)增加新成員。>>>deffunc():print(func.x)#查看函數(shù)func的成員x>>>func()#現(xiàn)在函數(shù)func還沒有成員x,出錯AttributeError:'function'objecthasnoattribute'x'>>>func.x=3#動態(tài)為函數(shù)增加新成員>>>func()3>>>func.x#在外部也可以直接訪問函數(shù)的成員3>>>delfunc.x#刪除函數(shù)成員>>>func()#刪除之后不可訪問AttributeError:'function'objecthasnoattribute'x'6.1函數(shù)定義函數(shù)的遞歸調(diào)用是函數(shù)調(diào)用的一種特殊情況,函數(shù)調(diào)用自己,自己再調(diào)用自己,自己再調(diào)用自己,...,當(dāng)某個條件得到滿足的時候就不再調(diào)用了,然后再一層一層地返回直到該函數(shù)第一次調(diào)用的位置。函數(shù)A函數(shù)B函數(shù)B函數(shù)B函數(shù)B函數(shù)B調(diào)用返回調(diào)用返回調(diào)用返回調(diào)用返回調(diào)用返回調(diào)用返回6.1函數(shù)定義6.2形參與實(shí)參函數(shù)定義時括弧內(nèi)為形參,一個函數(shù)可以沒有形參,但是括弧必須要有,表示該函數(shù)不接受參數(shù)。函數(shù)調(diào)用時向其傳遞實(shí)參,將實(shí)參引用傳遞給形參。在定義函數(shù)時,對參數(shù)個數(shù)并沒有限制,如果有多個形參,需要使用逗號進(jìn)行分隔。6.2形參與實(shí)參編寫函數(shù),接受兩個整數(shù),并輸出其中最大數(shù)。defprintMax(a,b):

ifa>b:

print(a,'isthemax')

else:

print(b,'isthemax')6.2形參與實(shí)參對于絕大多數(shù)情況下,在函數(shù)內(nèi)部直接修改形參的值不會影響實(shí)參,而是創(chuàng)建一個新變量。例如:>>>defaddOne(a):print(id(a),':',a)a+=1print(id(a),':',a)

>>>v=3>>>id(v)1599055008>>>addOne(v)1599055008:31599055040:4>>>v3>>>id(v2形參與實(shí)參在有些情況下,可以通過特殊的方式在函數(shù)內(nèi)部修改實(shí)參的值,例如下面的代碼。>>>defmodify(v):#修改列表元素值v[0]=v[0]+1>>>a=[2]>>>modify(a)>>>a[3]>>>defmodify(v,item):#為列表增加元素v.append(item)>>>a=[2]>>>modify(a,3)>>>a[2,3]6.2形參與實(shí)參也就是說,如果傳遞給函數(shù)的是可變序列,并且在函數(shù)內(nèi)部使用下標(biāo)或可變序列自身的方法增加、刪除元素或修改元素時,實(shí)參也得到相應(yīng)的修改。>>>defmodify(d):#修改字典元素值或?yàn)樽值湓黾釉豥['age']=38>>>a={'name':'Dong','age':37,'sex':'Male'}>>>a{'age':37,'name':'Dong','sex':'Male'}>>>modify(a)>>>a{'age':38,'name':'Dong','sex':'Male'}6.3參數(shù)類型在Python中,函數(shù)參數(shù)有很多種:可以為普通參數(shù)、默認(rèn)值參數(shù)、關(guān)鍵參數(shù)、可變長度參數(shù)等等。Python在定義函數(shù)時不需要指定形參的類型,完全由調(diào)用者傳遞的實(shí)參類型以及Python解釋器的理解和推斷來決定,類似于重載和泛型。Python函數(shù)定義時也不需要指定函數(shù)的類型,這將由函數(shù)中的return語句來決定,如果沒有return語句或者return沒有得到執(zhí)行,則認(rèn)為返回空值None。Python支持對函數(shù)參數(shù)和返回值類型的標(biāo)注,但實(shí)際上并不起任何作用,只是看起來方便。>>>deftest(x:int,y:int)->int:'''xandymustbeintegers,returnanintegerx+y'''assertisinstance(x,int),'xmustbeinteger'assertisinstance(y,int),'ymustbeinteger'z=x+yassertisinstance(z,int),'mustreturnaninteger'returnz>>>test(1,2)3>>>test(2,3.0)#參數(shù)類型不符合要求,拋出異常AssertionError:ymustbeinteger6.3參數(shù)類型位置參數(shù)(positionalarguments)是比較常用的形式,調(diào)用函數(shù)時實(shí)參和形參的順序必須嚴(yán)格一致,并且實(shí)參和形參的數(shù)量必須相同。>>>defdemo(a,b,c):print(a,b,c)>>>demo(3,4,5)#按位置傳遞參數(shù)345>>>demo(3,5,4)354>>>demo(1,2,3,4)#實(shí)參與形參數(shù)量必須相同TypeError:demo()takes3positionalargumentsbut4weregiven6.3參數(shù)類型6.3.1默認(rèn)值參數(shù)默認(rèn)值參數(shù)必須出現(xiàn)在函數(shù)參數(shù)列表的最右端,任何一個默認(rèn)值參數(shù)右邊不能有非默認(rèn)值參數(shù)。6.3.1默認(rèn)值參數(shù)調(diào)用帶有默認(rèn)值參數(shù)的函數(shù)時,可以不對默認(rèn)值參數(shù)進(jìn)行賦值,也可以為其賦值,具有很大的靈活性。>>>defsay(message,times=1):print(message*times)>>>say('hello')hello>>>say('hello',3)hellohellohello>>>say('hi',7)hihihihihihihi6.3.1默認(rèn)值參數(shù)下面的函數(shù)使用指定分隔符將列表中所有字符串元素連接成一個字符串。>>>defJoin(List,sep=None):return(sepor'').join(List)>>>aList=['a','b','c']>>>Join(aList)'abc'>>>Join(aList,',')'a,b,c'6.3.1默認(rèn)值參數(shù)默認(rèn)值參數(shù)如果使用不當(dāng),會導(dǎo)致很難發(fā)現(xiàn)的邏輯錯誤,例如:defdemo(newitem,old_list=[]):old_list.append(newitem)returnold_listprint(demo('5',[1,2,3,4]))#rightprint(demo('aaa',['a','b']))#rightprint(demo('a'))#rightprint(demo('b'))#wrong試著想一想,這段代碼會輸出什么呢?6.3.1默認(rèn)值參數(shù)上面的代碼輸出結(jié)果如下,最后一個結(jié)果是錯的。[1,2,3,4,'5']['a','b','aaa']['a']['a','b']繼續(xù)想:為什么會這樣呢?6.3.1默認(rèn)值參數(shù)原因在于默認(rèn)值參數(shù)的賦值只會在函數(shù)定義時被解釋一次。當(dāng)使用可變序列作為參數(shù)默認(rèn)值時,一定要謹(jǐn)慎操作。最后一個問題來了:正確的代碼該怎么寫呢?6.3.1默認(rèn)值參數(shù)終極解決方案:改成下面的樣子就不會有問題了defdemo(newitem,old_list=None):ifold_listisNone:old_list=[]new_list=old_list[:]new_list.append(newitem)returnnew_listprint(demo('5',[1,2,3,4]))print(demo('aaa',['a','b']))print(demo('a'))print(demo('b'))6.3.1默認(rèn)值參數(shù)注意:默認(rèn)值參數(shù)只在函數(shù)定義時被解釋一次可以使用“函數(shù)名.__defaults__”查看所有默認(rèn)參數(shù)的當(dāng)前值>>>i=3>>>deff(n=i):#參數(shù)n的值僅取決于i的當(dāng)前值print(n)>>>f()3>>>i=5#函數(shù)定義后修改i的值不影響參數(shù)n的默認(rèn)值>>>f()3>>>f.__defaults__#查看函數(shù)默認(rèn)值參數(shù)的當(dāng)前值(3,)6.3.2關(guān)鍵參數(shù)關(guān)鍵參數(shù)主要指實(shí)參,即調(diào)用函數(shù)時的參數(shù)傳遞方式。通過關(guān)鍵參數(shù),實(shí)參順序可以和形參順序不一致,但不影響傳遞結(jié)果,避免了用戶需要牢記位置參數(shù)順序的麻煩。>>>defdemo(a,b,c=5):print(a,b,c)>>>demo(3,7)375>>>demo(a=7,b=3,c=6)736>>>demo(c=8,a=9,b=0)9086.3.3可變長度參數(shù)可變長度參數(shù)主要有兩種形式:*parameter用來接受多個實(shí)參并將其放在一個元組中**parameter接受關(guān)鍵參數(shù)并存放到字典中6.3.3可變長度參數(shù)*parameter的用法>>>defdemo(*p):print(p)>>>demo(1,2,3)(1,2,3)>>>demo(1,2)(1,2)>>>demo(1,2,3,4,5,6,7)(1,2,3,4,5,6,7)6.3.3可變長度參數(shù)**parameter的用法>>>defdemo(**p):foriteminp.items():p

溫馨提示

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

評論

0/150

提交評論