計算機(jī)科學(xué)導(dǎo)論課件第4章_第1頁
計算機(jī)科學(xué)導(dǎo)論課件第4章_第2頁
計算機(jī)科學(xué)導(dǎo)論課件第4章_第3頁
計算機(jī)科學(xué)導(dǎo)論課件第4章_第4頁
計算機(jī)科學(xué)導(dǎo)論課件第4章_第5頁
已閱讀5頁,還剩111頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

簡潔的PythonPython內(nèi)置數(shù)據(jù)結(jié)構(gòu)Python賦值語句Python控制結(jié)構(gòu)Python函數(shù)調(diào)用Python自定義數(shù)據(jù)結(jié)構(gòu)Python自定義數(shù)據(jù)結(jié)構(gòu)有趣的小烏龜——Python之繪圖

1/TP

第4章Python學(xué)習(xí)引言

2前面的章節(jié)中,已經(jīng)接觸到一些Python程序,但并沒有專門介紹Python語言。本章會引導(dǎo)大家學(xué)習(xí)Python中一些基礎(chǔ)的語法,可以作為同學(xué)們編寫Python程序時的參考。4.1小節(jié)將對比Python與C/C++,來展示Python的簡潔性;4.2小節(jié),將介紹Python的常用內(nèi)置數(shù)據(jù)結(jié)構(gòu);4.3小節(jié)介紹Python的賦值語句;4.4小節(jié),將分別介紹if,while,for三種結(jié)構(gòu)控制語句;Python的函數(shù)調(diào)用的具體過程將在4.5小節(jié)介紹;除了內(nèi)置的數(shù)據(jù)結(jié)構(gòu),Python還支持自定義數(shù)據(jù)結(jié)構(gòu),這部分內(nèi)容將在4.6小節(jié)介紹。在學(xué)習(xí)Python語言的同時,本章也會介紹基本數(shù)據(jù)庫方面的知識,這些知識主要在兩方面教授。(1)Python的字典就是個類似數(shù)據(jù)庫關(guān)系的結(jié)構(gòu),利用唯一的“鍵”來獲取字典內(nèi)相關(guān)的信息記錄。(2)4.7小節(jié)介紹如何利用Python面向?qū)ο缶幊谭绞剑瑏韺崿F(xiàn)學(xué)生和課程數(shù)據(jù)庫的功能。4.8小節(jié)將向大家介紹Python中一個有趣的部分——繪圖。第1節(jié)簡潔的Python

3對比Python和C/C++兩種語言對同一問題的實現(xiàn)。對于一個存放整數(shù)的數(shù)組,如果要將數(shù)組中每個元素值加1的值打印出來:#<程序:c/c++數(shù)組各元素加1>#include<stdio.h>voidmain(){ intarr[5]={0,1,2,3,4}; inti,tmp; for(i=0;i<5;i++){ tmp=arr[i]+1; printf(“%d”,tmp); }}#<程序:Python數(shù)組各元素加1>arr=[0,1,2,3,4]foreinarr: tmp=e+1 print(tmp)簡潔的Python

4Python對該問題的實現(xiàn)明顯比C語言簡單很多。首先來分析一下這兩段代碼的不同之處:(1)C語言中,執(zhí)行的代碼必須要放置于函數(shù)中,而整個程序的入口地址是main函數(shù);Python并沒有這樣的強(qiáng)制規(guī)定。(2)C語言中所要使用的每一個變量都需要事先定義,并顯示的說明其類型,比如i,tmp。而Python中只需要在使用時,用賦值號“=”就可以了。(3)C語言在聲明數(shù)組時,必須定義數(shù)組大小,例子中定義了一個大小為5的數(shù)組arr。而Python沒有這樣的要求,直接定義數(shù)組元素即可。簡潔的Python

5(4)C語言在遍歷數(shù)組時,需要知道數(shù)組的大小以及計算索引值(index);而Python的for循環(huán)可以直接遍歷列表中的每一個值,這種方式將能大大提高編程效率。(5)C語言中,每條語句必須以“;”分號結(jié)束,而Python沒有這樣的強(qiáng)行規(guī)定,如果一行要寫多個語句,才必須用分號隔開,例如tmp=e+1;ptinte。(6)對于C語言,每一個語句塊(函數(shù),for循環(huán)……)都需要用{}花括號,而Python并不需要。C語言對每條語句的縮進(jìn)沒有硬性要求。而對于Python而言,同一個層次的語句必須要有相同的縮進(jìn)。Python優(yōu)點(diǎn)

6軟件質(zhì)量高:Python高度重視程序的可讀性、一致性。而且,Python支持面向?qū)ο蟪绦蛟O(shè)計(OOP,object-orientedprogramming),使得代碼的可重用性、可維護(hù)性更高。提高開發(fā)效率:Python語法簡單,使用方便。開發(fā)時需要錄入的代碼量也相對小很多,因此在調(diào)試、維護(hù)時也更容易。程序可移植性強(qiáng):大多數(shù)的Python程序在不同平臺上運(yùn)行時,都不需要做任何改變。標(biāo)準(zhǔn)庫的支持:Python提供了強(qiáng)大的標(biāo)準(zhǔn)庫支持,支持一系列復(fù)雜的編程任務(wù)。在網(wǎng)站開發(fā)、數(shù)值計算等各個方面都內(nèi)置了強(qiáng)大的標(biāo)準(zhǔn)庫。第2節(jié)Python內(nèi)置數(shù)據(jù)結(jié)構(gòu)

7Python基本數(shù)據(jù)類型列表(list)再談字符串字典(Dictionary)——類似數(shù)據(jù)庫的結(jié)構(gòu)引言

8CPU只認(rèn)識0與1,程序怎么區(qū)分存放在內(nèi)存中的0與1是什么呢?例如,地址1000H的內(nèi)容為(01100001)2,Python如何知道這個單元是存放的是字符“a”還是“97”呢?數(shù)據(jù)類型!是數(shù)據(jù)類型決定了這個單元的內(nèi)容是一個ASCII碼的字符“a”,或者是一個整數(shù)“97”。用高中所學(xué)的集合來定義數(shù)據(jù)類型,它是一個集合以及定義在這個集合上的一組操作。例如,定義一個整數(shù)I類型如下:I類型的數(shù)據(jù)集合為:Set={-32767,-32768…,-1,0,1,2,…,32767,32768},操作包括{+,-,*,/,%}。如果指定地址為1000H的內(nèi)存單元所存儲的內(nèi)容為I類型的數(shù)據(jù),那么該內(nèi)存單元存放的就是數(shù)值“97”。

9Python內(nèi)置數(shù)據(jù)類型數(shù)值類型整數(shù)類型(integer)浮點(diǎn)型(float)復(fù)數(shù)(complex

)布爾型(bool)字符串類型(string)序列列表(list)元組(tuple)映射字典(dictionary)——數(shù)據(jù)類型結(jié)構(gòu)圖自定義類型類(class)——數(shù)據(jù)類型2.1Python基本數(shù)據(jù)類型——整數(shù)類型

10如1,2,-3,100,9999均為整數(shù),在Python3.0之后的版本中,整數(shù)類型的數(shù)值集合包括了所有的整數(shù),并不會對整數(shù)的范圍進(jìn)行約束。這一點(diǎn)是非常有用的,在常見的編程語言中,單單是整數(shù)類型,就可以分為short,int,long,在這些語言中,整數(shù)所能支持的最大范圍通常為(-2,147,483,648至2,147,483,647)。Python為這些數(shù)據(jù)類型提供的操作,包括從小學(xué)所學(xué)的數(shù)字操作符:{+,-,*,/,()},以及取余運(yùn)算符:%,例如10%3結(jié)果為1。需要注意的是,除法“/”所得到的結(jié)果不是整數(shù)類型,而是浮點(diǎn)類型,比如9/3,得到的是3.0,要想得到整型3,需要使用“//”運(yùn)算符。另外,Python還提供了冪運(yùn)算(Power),使用“**”運(yùn)算符,比如需要計算52時,只需要輸入5**2即可。2.1Python基本數(shù)據(jù)類型——浮點(diǎn)型

11如5.0,1.6,200.985等有小數(shù)部分的數(shù)值為浮點(diǎn)型。其操作符與整數(shù)類型類似,唯一需要注意的是“//”運(yùn)算符在浮點(diǎn)數(shù)運(yùn)算中所得到的結(jié)果仍是浮點(diǎn)數(shù)類型,不過與“/”不同的是它將舍去小數(shù)部分。2.1Python基本數(shù)據(jù)類型——整數(shù)類型

12在編程中,經(jīng)常需要產(chǎn)生隨機(jī)數(shù),Python提供能方便的內(nèi)置函數(shù)以產(chǎn)生隨機(jī)數(shù)。在Python中,要產(chǎn)生隨機(jī)數(shù),首先要在文件首加上引入random模塊的語句,即importrandom。以下分別介紹使用Python如何產(chǎn)生隨機(jī)浮點(diǎn)數(shù)與隨機(jī)整數(shù)。左邊程序使用了random.uniform(a.b)函數(shù),該函數(shù)將生成一個介于a,b的浮點(diǎn)數(shù)。而右邊程序為生成隨機(jī)整數(shù)的函數(shù):random.randint(a,b),該函數(shù)將產(chǎn)生一個介于[a,b](包含a和b)的隨機(jī)整數(shù)。#<程序:產(chǎn)生10-20的隨機(jī)浮點(diǎn)數(shù)>importrandomf=random.uniform(10,20)print(f)#<程序:產(chǎn)生10-20的隨機(jī)整數(shù)>importrandomi=random.randint(10,20)print(i)2.1Python基本數(shù)據(jù)類型——布爾型

13在生活中經(jīng)常對某個疑問進(jìn)行“Yes”和“No”或“是”和“不是”的回答,在數(shù)學(xué)中,對判斷會作出“對”和“錯”的回答。為了在計算機(jī)語言中規(guī)范這種表達(dá),把結(jié)果是肯定的用“True”表示,把結(jié)果是否定的用“False”來表示。例如:#<程序:布爾類型例子>b=100<101print(b)這里,b是布爾類型變量,b=100<101為布爾表達(dá)式,運(yùn)行此段程序,將輸出True。布爾類變量只有二種可能值:True或False。Python提供一整套布爾比較和邏輯運(yùn)算,“<,>,<=,>=,==,!=”,分別為小于,大于,小于等于,大于等于,等于,不等于6種比較運(yùn)算符,以及“not,and,or”等邏輯運(yùn)算符。2.1Python基本數(shù)據(jù)類型——字符串型

14字符串是字符的序列,在Python中有多種方式表示字符串,本節(jié)僅介紹最常用的兩種,單引號與雙引號,回顧本書中第一章“HelloWorld”的例子,在打印HelloWorld時,使用了print("Helloworld!")。這里采用了雙引號來表示字符串類型,單引號‘Helloworld!’也可以表示字符串類型。如果輸入的字符串用雙引號表示,而字符串中有單引號,Python就會打印出用雙引號中的所有字符串。如print(“book‘sprice”)結(jié)果為book’sprice。2.2列表

15前面所講的字符串是一個序列,下面講述的列表也是一個十分常用的序列。字符串的聲明是在“”或者‘’內(nèi)的,對于列表,它的聲明形式為:L=[],執(zhí)行這條語句時,將產(chǎn)生一個空列表。列表中的元素以“,”相間隔,例如,語句L=[1,3,5]定義了一個含有三個元素的列表。元素之間用‘,’相間隔。來回顧一下第二章所討論過的數(shù)組,數(shù)組(Array)是由有限個元素組成有序集合,用序號進(jìn)行索引。事實上,列表就類似數(shù)組這個數(shù)據(jù)結(jié)構(gòu),它為每個元素分配了一個序號。在Python中,將這種有順序編號的結(jié)構(gòu)稱之為“序列”,序列主要包括:列表、元組、字符串等,本小節(jié)將介紹通用的序列操作以及列表,元組可以看成是不可以修改的列表,字符串的操作將在下一個小節(jié)進(jìn)行介紹。2.2列表

16需要注意的是,不同于數(shù)組,列表中的元素類型可以是不一樣的,也就是說,列表中的元素可以是整數(shù)型,浮點(diǎn)型,字符串,還可以是列表。例如,L=[1,1.3,’2’,”China”,[‘I’,’am’,’another’,’list’]]。這將給編程者帶來許多便利,即可以將不同元素類型融合到一個列表中,同時,需要提醒讀者的是,在對列表元素進(jìn)行操作時,一定要注意元素類型,例如上述的L,如L[0]+L[2]操作將產(chǎn)生錯誤,因為整數(shù)型不能與字符串相加,而str(L[0])+L[2],與L[0]+int(L[2])都是正確的,不過第一個表達(dá)式得到的結(jié)果為“12”,而第二個得到的結(jié)果為3。2.2列表——序列的通用操作

17序號操作符說明1seq[index]獲得下標(biāo)為index的元素2seq[index1:index2(:stride)]獲得下標(biāo)從index1到index2間的元素集合,步長為stride3seq1+seq2連接序列seq1和seq24seq*expr序列重復(fù)expr次5objinseq判斷obj元素是否包含在seq中序列的通用操作主要包括索引、分片、鏈接(加)、重復(fù)(乘),以及檢查某個元素是否屬于序列。序列中的所有元素都是有索引號的(注意:索引號是從0開始遞增的)。這些元素可以通過索引號分別訪問。如<程序:序列索引>所示,L是列表類型的變量,而程序中只打印出該列表的第一個元素。這時,就可以使用下標(biāo)操作符“[index]”來獲取,index稱之為下標(biāo)。#<程序:序列索引>L=[1,1.3,"2","China",["I","am","another","list"]]print(L[0])

該程序?qū)⑤敵稣麛?shù)1。Python的下標(biāo)操作符有一個很強(qiáng)大的功能,即索引值為負(fù)數(shù)時,它表示從序列最后一個元素開始計數(shù),例如,L[-1]可以獲得L的最后一個元素。需要注意的是,如果下標(biāo)值超出了序列的范圍,Python解釋器將會報錯,提示下標(biāo)超出范圍。比如,L的合法范圍是[-5,4]。2.2列表——序列的通用操作之索引

18Python對序列提供了強(qiáng)大的分片操作,運(yùn)算符仍然為下標(biāo)運(yùn)算符,而分片內(nèi)容通過冒號相隔的兩個索引來實現(xiàn)。例如,L[index1:index2]:index1是分片結(jié)果的第1個元素的索引號,而index2的值減去1是分片結(jié)果的最后一個元素在序列中的索引號。如果只希望獲得L的中三個元素:"2","China",和["I","am","another","list"],L[2:5]即可實現(xiàn)。如果index2≤index1,那么分片結(jié)果將為空串。如果index2置空,分片結(jié)果將包括索引為index1及之后的所有元素。所以,要打印出L中的"2","China",["I","am","another","list"],還可以使用L[2:]實現(xiàn)。index1也可以置空,表示從序列開頭0到index2的分片結(jié)果。而當(dāng)index1與index2都置空時,將復(fù)制整個序列,例如L[:](注意:這是很有用的方式來復(fù)制一個列表)。2.2列表——序列的通用操作之分片

19分片操作的形式還可以是L[index1:index2:stride],第三個數(shù)stride是步長,在沒有指定的情況下,默認(rèn)為1。如果步長大于1,那么就會跳過某些元素,例如,要得到L的奇數(shù)位的元素時,L[::2]即可實現(xiàn)。需要注意的是,步長不能為0,但可以為負(fù)數(shù),表示從右向左提取元素。例如,L[-1:-1-len(L):-1]會產(chǎn)生最后一個元素開始往前到第一個元素的序列,len(L)函數(shù)是返回序列L的長度。注意,分片操作是產(chǎn)生新的序列,不會改變原來的序列。2.2列表——序列的通用操作之分片

20兩個整數(shù)類型相加是整數(shù)值做加法,而對于兩個序列,加法則表示連接操作,需要注意的是,進(jìn)行操作的兩個序列必須是相同類型(字符串、列表、元組等)才可以進(jìn)行連接。比如,L1為[1,1.3],L2為[“2”,“China”,[“I”,“am”,“another”,“l(fā)ist”]],連接兩個序列L1+L2為:[1,1.3,“2”,“China”,[“I”,“am”,“another”,“l(fā)ist”]]序列的乘法表示將原來的序列重復(fù)多次。例如L=[0]*100會產(chǎn)生一個含有100個0的列表。這個操作對初始化一個有足夠長度的列表是有用的。2.2列表——序列的通用操作之加與乘

21要判斷某個元素是否在序列中,可以使用in運(yùn)算符,其返回值為一個布爾值,如果為True,表示元素屬于序列。例如要判斷“China”是否屬于L,可以使用"China"inL實現(xiàn)。要實現(xiàn)相反的操作,即判斷某個元素是否不在序列中,可以使用notin運(yùn)算符。2.2列表——序列的通用操作之檢查某個元素是否屬于序列

222.2列表——序列的實用函數(shù)

23序號函數(shù)說明1len(seq)返回序列seq的元素個數(shù)2min(seq)返回序列中的"最小值"3max(seq)返回序列中的"最大值"4sum(seq[index1:index2])序列求和。(注:字符串類型不適用)序列除了擁有如上所列的通用操作之外,Python還為序列提供了一些實用函數(shù),以實現(xiàn)一些常用功能,比如求一個序列包含的元素數(shù)量,序列中的最大值、最小值,以及求和等操作。如下表所示:2.2列表——列表的專有方法

24除了實現(xiàn)序列的通用操作及函數(shù)外,列表還提供了額外的很多方法(method),這里所說的方法事實上與函數(shù)是一個概念,不過,它是專屬于列表的,其他的序列類型是無法使用這些方法的。這些專用方法的調(diào)用方式也與通用序列函數(shù)調(diào)用方式不同。如果要統(tǒng)計列表L的長度,使用len函數(shù),其調(diào)用語句為len(L),這個函數(shù)調(diào)用意味著要將L作為參數(shù)傳遞給len函數(shù)。但是,如果是要使用列表的專用方法時,方法的調(diào)用形式是L.method(parameter),其中parameter不包含L,在調(diào)用這些專用方法時,并不會顯式地傳遞L。另外需要注意的是,這里使用了“.”操作符,該操作符意味著要調(diào)用的方法是列表L的方法。舉個例子,列表有一個append(e)方法,該方法的作用是將e插入列表L的末尾。如果對一個非列表類型的變量,如元組,字符串,調(diào)用append方法,Python將會報錯,因為這些序列并沒有定義屬于列表的專用方法,當(dāng)然,這些序列也有自己專用的方法。2.2列表——列表的專有方法

25下表給出了列表的常用的方法,操作的初始列表為s=[1,2],參數(shù)中的[]符號表示該參數(shù)可以傳遞也可以不傳遞,如L.pop(),若不傳遞參數(shù),s將最后一個元素彈出,否則L.pop(i)將彈出L中第i號位置的元素。函數(shù)作用/返回參數(shù)L結(jié)果/返回1s.append(x)將一個數(shù)據(jù)添加到列表s的末尾'3'[1,2,'3']2s.clear()刪除列表s的所有元素?zé)o[]3s.copy()返回與s內(nèi)容一樣的列表無[1,2]/[1,2]4s.extend(t)將列表t添加到列表s的末尾['3','4'][1,2,'3','4']5s.insert(i,x)將數(shù)據(jù)x插入到s的第i號位置0,'3'['3',1,2]6s.pop(i)將列表s第i個元素彈出并返回其值1或無[1]/27s.remove(x)刪除列表s中第一個值為x的元素1[2]8s.reverse()反轉(zhuǎn)s中的所有元素?zé)o[2,1]2.2列表——遍歷

26遍歷,即要依次對列表中的所有元素進(jìn)行訪問(操作),對列表這種線性數(shù)據(jù)結(jié)構(gòu)最自然的遍歷方式就是循環(huán)。在前面章節(jié)有提到過,Python提供while以及for兩種循環(huán)語句,本小結(jié)將首先簡單回顧這兩個循環(huán)語句的使用;然后,分別使用這兩種循環(huán)語句對列表進(jìn)行遍歷。2.2列表——遍歷之while循環(huán)

27while循環(huán)的一般格式如下:首行會對一個bool變量<test1>進(jìn)行檢測,下面是要重復(fù)的語句塊<語句塊1>,在執(zhí)行完<語句塊1>后重新回到while首行檢查<test1>的值。最后有一個可選的else部分,如果在循環(huán)體中沒有遇到break語句,就會執(zhí)行else部分,即<語句塊2>。while<test1>: <語句塊1>else: <語句塊2>2.2列表——遍歷之for循環(huán)

28for循環(huán)的一般格式如下:首行會定義一個賦值目標(biāo)<target>,in后面跟著要遍歷的對象<object>,下面是想要重復(fù)的語句塊。同while循環(huán),for循環(huán)也有一個else子句,如果在for循環(huán)的結(jié)構(gòu)體中遇到break語句,那么就會執(zhí)行else子句。for<target>in<object>: <語句塊1>else: <語句塊2>執(zhí)行for循環(huán)時,對象<object>中的每一個元素都會賦值給目標(biāo)<target>,然后為每個元素執(zhí)行一遍循環(huán)體。賦值目標(biāo)<object>可以是一個新的變量名,它的作用范圍就是所在的for循環(huán)結(jié)構(gòu)。2.2列表——遍歷實現(xiàn)

29思考如下問題:對列表L=[1,3,5,7,9,11]進(jìn)行遍歷,要求每次輸出所遍歷到的元素值加1。下面分別使用while循環(huán)與for循環(huán)對這個問題進(jìn)行實現(xiàn)。從實現(xiàn)的兩個例子可以看出,對列表進(jìn)行遍歷,for循環(huán)比while循環(huán)更容易。也可以利用前面講的分片技巧來完成遍歷部分元素。例如L=[1,2,3,4],“foreinL[-1:-5:-1]”語句會從最后一個元素來反向遍歷所有元素。另外用range()函數(shù)也可以產(chǎn)生遍歷的索引,例如range(0,len(L))就產(chǎn)生了從0開始到(len(L)-1)的全部索引。而range(len(L)-1,-1,0)就產(chǎn)生了從len(L)-1開始到0的索引。也可以用list(range(0:x))來產(chǎn)生一個從0開始到x-1的列表[0,1,2,…,x-1]。range()函數(shù)應(yīng)用很廣,在后面講述for循環(huán)結(jié)構(gòu)時我們會詳細(xì)講述range()函數(shù)。#<程序:while循環(huán)對列表進(jìn)行遍歷>L=[1,3,5,7,9,11]mlen=len(L)i=0while(i<mlen):print(L[i]+1)i+=1#<程序:for循環(huán)對列表進(jìn)行遍歷>L=[1,3,5,7,9,11]foreinL: e+=1print(e)2.3再談字符串

30細(xì)心的同學(xué)會發(fā)現(xiàn),前面在介紹了字符串的表達(dá)方式,并沒有給出在字符串的操作。數(shù)值類型有“+,-,*,/”等操作,布爾型有“not,and,or”等邏輯運(yùn)算符,同樣的,字符串也有其運(yùn)算符,功能甚至遠(yuǎn)遠(yuǎn)超過其它兩種數(shù)據(jù)類型。事實上,在4.2.2中提到,字符串同列表一樣,也是一個序列。同列表一樣,字符串也實現(xiàn)了序列的通用操作與函數(shù)。但是需要注意的是,字符串內(nèi)容是不可改變(immutable變量)。字符串對某一個索引所在位置進(jìn)行賦值是不允許的,例如,s=“Helloworld?”,想要將”?”改為”!”,如果使用s[11]=’!’,這是不允許的。另外,在列表中,一個列表變量調(diào)用自己的專用方法,將反應(yīng)到列表本身,但在字符串中,調(diào)用其自己的專用方法,其自身的內(nèi)容是不變的。2.3再談字符串——字符串專用方法

31除了實現(xiàn)“序列”的通用操作及函數(shù)外,字符串類型還提供了額外的很多實用方法(method),在此將給出了字符串的常用的10個方法并給出了相應(yīng)的范例,參數(shù)中的[]表示調(diào)用方法時,該參數(shù)可以傳遞也可以省略。例如,str=“HEllO”,str.count(‘O’)與str.count(‘O’,2),以及str.count(‘O’,2,4)的語法都是正確的,但是第一個調(diào)用表示統(tǒng)計整個字符串中的’O’,第二個調(diào)用表示統(tǒng)計從2號索引開始到結(jié)束出現(xiàn)’O’的次數(shù),而第三個調(diào)用表示統(tǒng)計str中索引為2和3位置’O’出現(xiàn)的次數(shù)。2.3再談字符串——字符串專用方法

32函數(shù)作用/返回參數(shù)print結(jié)果1str.capitalize()首字母大寫,其它小寫的字符串無Hello2str.count(sub[,start[,end]])統(tǒng)計sub字符串出現(xiàn)的次數(shù)'O'13str.isalnum()判斷是否是字母或數(shù)字無TRUE4str.isalpha()判斷是否是字母無TRUE5str.isdigit()判斷是否是數(shù)字無FALSE6str.strip([chars])開頭結(jié)尾不包含chars中的字符'HEO''ll'7str.split([sep],[maxsplit])以sep為分隔符分割字符串'll'['HE','O']8str.upper()返回字符均為大寫的str無HELLO9str.find(sub[,start[,end]])查找sub第一次出現(xiàn)的位置'll'210str.replace(old,new[,count])在str中,用new替換old'l','L'HELLO2.3再談字符串——字符串與數(shù)值型相互轉(zhuǎn)化

33在編程過程中,常遇到的一個問題是字符串類型與數(shù)值類型之間進(jìn)行轉(zhuǎn)換。首先討論如何將數(shù)值類型轉(zhuǎn)化為字符串類型,函數(shù)str()可以實現(xiàn)這個功能,例如s=str(123.45),執(zhí)行該語句后,s的值為“123.45”。將字符串類型轉(zhuǎn)化為數(shù)值類型就有些復(fù)雜了。我們知道,數(shù)值類型可以分為整數(shù)類型和浮點(diǎn)數(shù)類型。將字符串類型轉(zhuǎn)換成相應(yīng)的數(shù)值類型則需要調(diào)用相應(yīng)的轉(zhuǎn)換函數(shù)。例如,int()函數(shù)可以將字符串轉(zhuǎn)化為整數(shù),float()函數(shù)可以將字符串轉(zhuǎn)化為浮點(diǎn)數(shù),比如str=”123”,那么int(str)的返回值為123;如果str=“123.45”,那么float(str)的返回值為123.45。2.3再談字符串——字符串轉(zhuǎn)化為列表

34字符串轉(zhuǎn)化為列表也是十分常用的一個操作,本小節(jié)將講解如何將字符串轉(zhuǎn)化為列表。如果希望將字符串的每一個字符作為一個元素保存在一個列表中,可以使用list()函數(shù),比如str=“123,45”,list(str)的返回值為[‘1’,‘2’,‘3’,‘,’,‘’,‘4’,‘5’]。注意逗號’,’和空白‘’都當(dāng)做一個字符。如果希望將字符串分開,那么可以使用字符串專用方法split。例如,str=“123,45”,將其以“,”分割,使用L=str.split(“,”)便可實現(xiàn)。其返回值是一個列表[“123”,“45”],需要注意的是,得到的列表中每個元素都是字符串類型,空白仍然在字符串“45”里面的。如果要得到整數(shù)類型的,還需要將字符串轉(zhuǎn)化為數(shù)值,例如,使用如下語句:L=[int(e)foreinL]可將L=[“123”,“45”]轉(zhuǎn)化為單純的整數(shù)列表L=[123,45]。2.4字典

35字符串、列表、元組都是序列,而Python的基本數(shù)據(jù)結(jié)構(gòu),除了序列外,還包括映射,簡單來說,序列中存放的每個數(shù)據(jù)都是單獨(dú)的一個元素,數(shù)據(jù)和數(shù)據(jù)之間沒有直接的聯(lián)系,比如s="Helloworld!"這個例子中,字符串s是一個序列,它包含了12個單獨(dú)的數(shù)據(jù)元素:'H','e','l'……但是,如果要存儲映射關(guān)系,單個序列是做不到的。而映射(mapping)這個數(shù)據(jù)結(jié)構(gòu)就是用來完成此任務(wù)的,回憶一下高中所學(xué)的函數(shù)概念。定義:設(shè)X、Y是兩個非空集合,如果存在一個法則f,使得對X中每個元素x,按法則f,在Y中有唯一確定的元素y與之對應(yīng),則稱f為X到Y(jié)的映射,記作:f:X→Y。集合X為f的定義域(domain),集合Y為f的值域(range),要注意的是對映射f,每個x∈X,有唯一確定的y=f(x)與之對應(yīng),也就是說,映射可以是一對一映射,也可以是多對一映射。2.4字典——映射

36根據(jù)映射的定義,圖4.1中(1)、(2)均為映射,而(3)不是映射。在Python中,映射數(shù)據(jù)類型也滿足這個定義。2.4字典

37字典是Python中唯一的映射類型。字典的形式為{}。同列表一樣,Python中既可以創(chuàng)建空字典,也可以直接創(chuàng)建帶有元素的字典。字典中的每一個元素都是一個鍵值對(Key:Value),而鍵Key在字典中只會出現(xiàn)一次,也就是大家知道函數(shù)是不可以有一對多的映射關(guān)系。鍵是集合X中的一個元素,而Value指的是集合Y中的一個元素,而f(key)=value。比如要存放“Hello”中每個字符出現(xiàn)的頻次數(shù),mdict={‘H’:1,’e’:1,’l’:2,‘o’:1},這個例子中X={‘H’,‘e’,‘l’,‘o’},Y={1,2},而mdict(’H’)=1,mdict(‘l’)=2,……2.4字典——類似數(shù)據(jù)庫的結(jié)構(gòu)

38Python中提供字典這個映射類型,使得Python對數(shù)據(jù)的組織、使用更加靈活。Python字典是符合數(shù)據(jù)庫數(shù)據(jù)表格的概念,它能夠表示基于關(guān)系模型的數(shù)據(jù)庫,即關(guān)系數(shù)據(jù)庫。而現(xiàn)在主流的數(shù)據(jù)庫oracle、db2、sqlserver、sybase、mysql等都是關(guān)系數(shù)據(jù)庫。為了理解Python的字典類型如何表示關(guān)系模型,下面將介紹關(guān)系數(shù)據(jù)庫中的基本概念。2.4字典——類似數(shù)據(jù)庫的結(jié)構(gòu)

39關(guān)系模型中最基本的概念是關(guān)系(relation)。上表給出的“字符頻次表”就是一個關(guān)系。關(guān)系中的每一行(row)稱為一個記錄;每一列(column)稱為一個屬性。在每一個關(guān)系結(jié)構(gòu)中,我們必須要有“鍵”(key)作為尋找記錄的依據(jù)。所以必須有某一個屬性或者屬性組的值在這個關(guān)系表中是唯一的。這個屬性或?qū)傩越M稱為該關(guān)系的鍵(key)。例如,(H,1,0.2)為一個元組;該關(guān)系一共有三個屬性:字符、頻次、頻率;用字符屬性可以對應(yīng)某一個特定記錄的。字符頻次頻率H10.2e10.2l20.4o10.22.4字典——類似數(shù)據(jù)庫的結(jié)構(gòu)

40字典中的鍵值對,對應(yīng)于關(guān)系中的記錄;鍵,對應(yīng)于關(guān)系中的鍵;值,可以對應(yīng)于關(guān)系中的屬性。我們用f(x)=y來表示關(guān)系的話,在Python字典中是可以很靈活的定義x和y的結(jié)構(gòu)。x可以是用Python的元祖類型(不可以修改的列表),y可以是列表或字典類型。這就相當(dāng)于當(dāng)關(guān)系中的鍵x是多個屬性組成時,在Python中可以用元祖的方式來表示x。當(dāng)對于屬性y有多個值時,Python中也可以用列表或字典的形式來表示y。字符頻次表中的關(guān)系可使用Python中的字典進(jìn)行存放,如:mdict='H':[1,0.2],'e':[1,0.2],'l':[2,0.4],'o':[1,0.2]},這時,mdict[‘H’][1]即為字母’H’出現(xiàn)的頻率;對于該關(guān)系,Python還有另一種表達(dá)形式,即f(x)=y中的y還可以是字典類型,如:mdict2={'H':{'count':1,'freq':0.2},'e':{'count':1,'freq':0.2},'l':{'count':2,'freq':0.4},'o':{'count':1,'freq':0.2}},這時,mdict2['H']['freq']表示字母’H’出現(xiàn)的頻率。第一種方式,要獲取一個記錄的某個屬性,需要知道該屬性在記錄中的索引順序;而第二種方式,要獲取一個記錄的某個屬性,需要給出屬性名。2.4字典——專用方法

41與序列一樣,映射也有內(nèi)置操作符與內(nèi)置函數(shù),最常用的內(nèi)置操作符仍然是下標(biāo)操作符[],例如mdict[‘H’],將返回鍵’H’所對應(yīng)的value,即1。操作符[]也可以作為字典賦值使用。例如,mdict[‘H’]=1,假如mdict里面沒有‘H’、這個鍵,就會將‘H’:1加入mdict里面,假如有‘H’這個鍵,其值就被更改為1了。另外,in與notin在字典中仍然適用,例如’o’inmdict將返回True,而’z’inmdict將返回False;最常用的函數(shù)是len(dict),它將返回字典中鍵值對的個數(shù),例如,len(mdict)將返回4。2.4字典——專用方法

42函數(shù)作用/返回參數(shù)print結(jié)果1mdict.clear()清空mdict的鍵值對無{}2mdict.copy()得到字典mdict的一個拷貝無{'H':1,'e':2}3mdict.has_key(key)判斷key是否在mdict中H/hTrue/False4mdict.items()得到一個list的全部鍵值對無[('H',1),('e',2)]5mdict.keys()得到一個list的全部鍵個鍵無['H','e']6mdict.update([b])以b字典更新a字典{'H':3}{'H':3,'e':2}7mdict.values()得到一個list的全部值無[1,2]8mdict.get(k[,x])若mdict[k]存在則返回,否則返回x'o',009mdict.setdefault(k[,x])若mdict[k]不存在,則添加k:x'x':3{'H':1,'e':2,'x':3}10mdict.pop(k[,x])若mdict[k]存在,則刪除H{'e':2}2.4字典——例子

43統(tǒng)計給定字符串mstr=“Helloworld,IamusingPythontoprogram,itisveryeasytoimplement.”中各個字符出現(xiàn)的次數(shù)。分析:要完成這項任務(wù),要對字符串的每一個字符進(jìn)行遍歷,將該字符作為鍵插入字典,或更新其出現(xiàn)次數(shù)。在4.2.3節(jié)中,介紹了如何將字符串轉(zhuǎn)化為列表,這里將使用這些技巧。#<程序:統(tǒng)計字符串中各字符出現(xiàn)次數(shù)>mstr="Helloworld,IamusingPythontoprogram,itisveryeasytoimplement."mlist=list(mstr)mdict={}foreinmlist: ifmdict.get(e,-1)==-1: #還沒出現(xiàn)過 mdict[e]=1 else: #出現(xiàn)過

mdict[e]+=1forkey,valueinmdict.items(): print(key,value)第3節(jié)Python賦值語句

44基本賦值語句序列賦值擴(kuò)展序列賦值多目標(biāo)賦值增強(qiáng)賦值語句引言

45賦值語句是程序語言中最基本的語句,通常用于給變量賦值。Python中創(chuàng)建一個變量,不需要聲明其類型。如在C/C++等語言中,定義一個整數(shù)i,并為其賦值10。語句如下:inti;i=10;而在Python中,只需要一條語句i=10即可。本節(jié)將介紹Python中常見的幾種賦值語句。3.1基本賦值語句

46#<程序:基本賦值語句>x=1;y=2k=x+yprint(k)運(yùn)行結(jié)果:3基本形式的賦值語句就是“變量x=值”。例如,給變量x和y分別賦值為1,2,將相加后的結(jié)果賦給變量k,并打印出k的值:運(yùn)行結(jié)果:3。3.2序列賦值

47#<程序:序列賦值語句>a,b=4,5print(a,b)a,b=(6,7)print(a,b)a,b="AB"print(a,b)((a,b),c)=('AB','CD')#嵌套序列賦值print(a,b,c)運(yùn)行結(jié)果:4567ABABCDPython中支持序列賦值,可以把賦值運(yùn)算符”=”右側(cè)的一系列值,依次賦給左側(cè)的變量?!?”的右側(cè)可以是任意類型的序列,如元組(對象的集合),列表,字符串,甚至序列的分片?!?”左側(cè)還支持嵌套的序列。3.3擴(kuò)展序列賦值

48#<程序:擴(kuò)展序列賦值語句>i,*j=range(3)print(i,j)運(yùn)行結(jié)果:0,[1,2]在之前的序列賦值中,賦值運(yùn)算符左側(cè)的變量個數(shù)和右側(cè)值的個數(shù)總是相等的。如果不相等,Python就報錯。Python中使用帶有星號的名稱,如*j,實現(xiàn)了擴(kuò)展序列賦值。正如所看到的,不帶星號的變量會先匹配相應(yīng)的內(nèi)容,而帶星號的變量會自動匹配所有剩下的內(nèi)容。3.4多目標(biāo)賦值

49#<程序:多目標(biāo)賦值語句1>i=j=k=3print(i,j,k)i=i+2#改變i的值,并不會影響到j(luò),kprint(i,j,k)運(yùn)行結(jié)果:333533#<程序:多目標(biāo)賦值語句2>i=j=[] #[]表示空的列表i.append(30)#向列表i中添加一個元素30 #列表j也受到影響print(i,j)i=[];j=[]i.append(30)print(i,j)運(yùn)行結(jié)果:[30][30][30][]多目標(biāo)賦值語句,可以把變量值一次性賦給多個變量。這里,變量i加2,并不會使得j和k加2。這是因為i,j為immutable對象。但如果賦值運(yùn)算符”=”的右側(cè)是mutable對象(如列表,字典等),變量i通過調(diào)用自身的專用方法而進(jìn)行改變會影響變量j的內(nèi)容。3.5增強(qiáng)賦值語句

50#<程序:增強(qiáng)賦值語句1>i=2i*=3#等價于i=i*3print(i)運(yùn)行結(jié)果:6#<程序:增強(qiáng)賦值語句2>L=[1,2];L1=L;L+=[4,5]print(L,L1)運(yùn)行結(jié)果:[1,2,4,5][1,2,4,5]增強(qiáng)賦值語句是從C語言借鑒而來,實質(zhì)上是基本賦值語句的簡寫。通常來說,增強(qiáng)賦值語句的運(yùn)行會更快一些。將變量x增加y賦給變量x,基本賦值語句為:x=x+y,增強(qiáng)賦值語句則為:x+=y

。相應(yīng)的,還有+=,*=,-=等等。對其中一個mutable對象的修改,會影響到其它變量。而使用增強(qiáng)賦值語句,也會引起這類問題。3.5增強(qiáng)賦值語句

51#<程序:增強(qiáng)賦值語句3>L=[1,2];L1=L;L=L+[4,5]print(L,L1)運(yùn)行結(jié)果:[1,2,4,5][1,2]如果不使用增強(qiáng)賦值語句的表達(dá),而使用基本賦值語句,對L的改變將不會影響其他變量??梢钥吹?,可變對象使用增強(qiáng)賦值形式時,變量將在原處進(jìn)行修改,所有引用它的對象也都會受到影響。第4節(jié)Python控制結(jié)構(gòu)

52if語句while循環(huán)語句for循環(huán)語句引言

53在第一章、第三章都介紹過計算機(jī)語言中的控制結(jié)構(gòu),有if選擇,while循環(huán)和for循環(huán)。這三種控制結(jié)構(gòu)是程序中重要的組成部分。在本節(jié)中,將分別介紹Python語言中的這三種控制結(jié)構(gòu)。4.1if語句

54Python的if語句流程如下:首先進(jìn)行條件測試,與其同層次可以有一個或多個可選的elif語句,最后可以有else塊。一般形式如下:

if(test1): <語句塊1> elif(test2): <語句塊2> elif(test3): <語句塊3> …… else: <語句塊n>4.1if語句

55if語句執(zhí)行時,首先檢測test1的值為真或是假,若為真,則執(zhí)行語句塊1;否則看test2的值為真或是假,若為真,則執(zhí)行語句塊2;否則看test3的值為真或是假,依次進(jìn)行判斷……若前面這些測試都為假,則執(zhí)行語句塊n。if語句總是選擇第一個測試為真的語句塊執(zhí)行,若都不為真,最后執(zhí)行else的語句塊。Python以縮進(jìn)來區(qū)別語句塊,上述例子中的if、elif和else能夠組成一個有特定邏輯的控制結(jié)構(gòu),有相同的縮進(jìn)。每一個語句塊中的語句也要遵循這一原則。4.1if語句——例子

56例如,在統(tǒng)計成績時,需要將一個百分制的成績轉(zhuǎn)化為Excellent、VeryGood、Good、Pass、Fail五個等級。#<程序:if語句實現(xiàn)百分制轉(zhuǎn)等級制>defif_test(score): if(score>=90): print('Excellent') elif(score>=80): print('VeryGood') elif(score>=70): print('Good') elif(score>=60): print('Pass') else: print('Fail')if_test(88)輸出結(jié)果:VeryGood4.1if語句——例子

57這個程序運(yùn)行如下:首先測試score>=90是否為真,若為真,則輸入Excellent,結(jié)束if語句,否則,測試score>=80···如果最終進(jìn)入了else的語句塊,那么表明score<60,輸出Fail并退出。也就是說,if語句將0-100劃分成了5個分?jǐn)?shù)區(qū)間:[90,100],[80,90),[70,80),[60,70),以及[0,60)。如果一個成績大于等于95分,在輸出Excellent后還要輸出一個“*”,這時,就需要使用嵌套if語句,實現(xiàn)如下。#<程序:if語句舉例—擴(kuò)展>defif_test(score): if(score>=90): print('Excellent',end='') if(score>=95): print('*') else: print('') elif…….if_test(98)4.1if語句

58if語句塊中嵌套了一個if結(jié)構(gòu),區(qū)分每條語句屬于哪一個if結(jié)構(gòu)很重要。圖4.1給出了這段代碼的塊結(jié)構(gòu)。上面這段代碼,有三個模塊。第一個if結(jié)構(gòu)由if語句及else語句構(gòu)成,將程序分為兩個語句塊,外層語句塊1和外層語句塊2,第二個if結(jié)構(gòu)嵌套在第一個if結(jié)構(gòu)的if語句內(nèi),構(gòu)成一個內(nèi)層語句塊1。4.1if語句——縮進(jìn)

59Python語言通過縮進(jìn)反映代碼的邏輯性??s進(jìn)可以由任意的空格和制表符組成,只要同一個語句塊的縮進(jìn)必須保持一致。一般來說,縮進(jìn)的距離為4個空格或者一個制表符。但是要注意,在同一段代碼中,混合使用制表符和空格并不是一個好習(xí)慣。因為不同的編輯器對制表符和空格混用的處理方式并不同,為了避免出錯,最好采用同一種形式的縮進(jìn)。4.2while循環(huán)語句

60Python中有兩個主要的循環(huán)結(jié)構(gòu):while循環(huán)和for循環(huán)。當(dāng)一部分操作需要重復(fù)執(zhí)行時,則采用循環(huán)結(jié)構(gòu)。while循環(huán)是Python語言中最通用的循環(huán)結(jié)構(gòu)。While結(jié)構(gòu)會重復(fù)測試布爾表達(dá)式,如果測試條件一直滿足,那么就會重復(fù)執(zhí)行循環(huán)結(jié)構(gòu)里面的語句(循環(huán)體)。Python的while循環(huán)結(jié)構(gòu)頂部,有一個布爾表達(dá)式,下面是循環(huán)體,有縮進(jìn)。之后有一個可選的else部分,如果在循環(huán)體中沒有遇到break語句,就會執(zhí)行else部分。形式如下:while<test1>: <語句塊1>else: <語句塊2>4.2while循環(huán)語句

61Python先判斷test1表達(dá)式的值為真或者假,如果為真,則執(zhí)行語句塊1。執(zhí)行完語句塊1后,會再次判斷test1表達(dá)式的值為真或者假,再決定是否執(zhí)行語句塊1,直到test1的值為假,退出循環(huán)體,進(jìn)入else語句塊。一個最簡單的while循環(huán)的例子如下:#<程序:while循環(huán)例子1>i=1whileTrue:print(i,'printing')i=i+1程序會一直運(yùn)行,一直打印“iprinting”語句。Python中的關(guān)鍵字True和1都表示布爾真值,也就是永遠(yuǎn)為真,所以會一直重復(fù)執(zhí)行print語句,而這種情況被稱之為“死循環(huán)”。計算機(jī)會被這個死循環(huán)永遠(yuǎn)占用而導(dǎo)致死機(jī)嗎?不會的,在介紹操作系統(tǒng)時會有清晰的答案。輸出:1printing2printing…4.2while循環(huán)語句——例子

62通常情況下,while循環(huán)的循環(huán)體中會有語句來修改布爾表達(dá)式中的變量。比如,需要從大到小輸出2*x,其中x是大于0且小于等于10的整數(shù),下面程序?qū)⑼瓿稍摴δ埽?<程序:while循環(huán)實現(xiàn)從大到小輸出2*x,0<x<=10>x=10whilex>0:print(2*x,end='')x=x-1輸出結(jié)果:2018161412108642執(zhí)行步驟如下:x=10,先判斷x>0為True,執(zhí)行print,打印出20;執(zhí)行x減1操作,得x=9;重復(fù)執(zhí)行(1),(2)。直到x的值為0,此時布爾表達(dá)式值為False,退出循環(huán)。(注:布爾表達(dá)式處若為數(shù)值類型,當(dāng)值為0時表示False,一切非0值表示True。)4.2while循環(huán)語句

63到此給出了while循環(huán)的一般控制流程,即檢測語句<test1>的布爾值,若為真,執(zhí)行<語句塊1>,再檢測語句<test1>,直到語句<test1>的布爾值為假。但是,在循環(huán)的過程中,時常需要改變循環(huán)的控制流程,比如在檢測到某個條件時,該次循環(huán)不需要進(jìn)行,又或者在檢測到某個條件時,需要退出循環(huán)。這時就需要引入兩個新的語句來完成這兩項功能,它們分別是continue與break。需要注意的是,這兩個語句通常是某條件滿足后執(zhí)行,所以常常放置于if語句中。下面將會分別介紹continue與break。4.2while循環(huán)語句——continue語句

64continue語句在循環(huán)結(jié)構(gòu)中執(zhí)行時,將會立即結(jié)束本次循環(huán),重新開始下一輪循環(huán),也就是說,跳過循環(huán)體中在continue語句之后的所有語句,繼續(xù)下一輪循環(huán)。回到上一小節(jié)的例子:需要從大到小輸出2*x,其中x是大于0且小于等于10的整。但是,現(xiàn)在有限制條件,當(dāng)x不能為3的倍數(shù),這時,就可以檢測當(dāng)x為3的倍數(shù)時,跳過輸出語句,進(jìn)入下一輪循環(huán)。#<程序:while循環(huán)實現(xiàn)從大到小輸出2*x,x不是3的倍數(shù)>x=10whilex>0:ifx%3==0:x=x-1continueprint(2*x,end='')x=x-1輸出結(jié)果:201614108424.2while循環(huán)語句——break語句

65break語句在循環(huán)結(jié)構(gòu)中執(zhí)行時,它會導(dǎo)致立即跳出循環(huán)結(jié)構(gòu),轉(zhuǎn)而執(zhí)行while結(jié)構(gòu)后面的語句。也就是說,雖然while<test1>:中,<test1>的值并不是False,但是,循環(huán)仍然可以結(jié)束?;氐角懊娴睦樱盒枰獜拇蟮叫≥敵?*x,其中x是大于0且小于等于10的整。但是,現(xiàn)在的限制條件變?yōu)?,?dāng)x第一次為6的倍數(shù)時,不打印2*x并退出循環(huán)。這時,就需要檢測當(dāng)x為6的倍數(shù)時,執(zhí)行break語句環(huán)。#<程序:while循環(huán)實現(xiàn)從大到小輸出2*x,x第一次為6的倍數(shù)時退出循環(huán)>x=10whilex>0:ifx%6==0:breakprint(2*x,end='')x=x-1輸出結(jié)果:201816144.2while循環(huán)語句——break語句

66結(jié)果顯示,當(dāng)x第一次為6的倍數(shù)時,也就是x=6時,退出循環(huán),之后x小于等于6的結(jié)果都不會輸出。這里的if語句中不需要有x=x-1,因為執(zhí)行到break語句時已經(jīng)退出循環(huán)了,不需要再對<test1>進(jìn)行檢測了。break語句還可以讓一個死循環(huán)“起死回生”。還記得while循環(huán)的第一個例子,不停地打印“iprinting”,這個時候,如果只希望打印2次,break可以用來實現(xiàn)。#<程序:while循環(huán)例子1改進(jìn)>i=1whileTrue:print(i,'printing')ifi==2:breaki=i+1輸出結(jié)果:1printing2printing4.2while循環(huán)語句——else語句

67while結(jié)構(gòu)中還有一個可選部分else,在while循環(huán)體執(zhí)行結(jié)束后,會執(zhí)行else的語句塊(不管while里面是否執(zhí)行)。但是當(dāng)break語句和else子句結(jié)合時,假如是因為break離開while,則else部分就不會被執(zhí)行。所以else一定是和while里的break相結(jié)合考慮,才有意義。下面是一個判斷正整數(shù)b是否為質(zhì)數(shù)的例子。#<程序:判斷b是否為質(zhì)數(shù)>b=7a=b//2whilea>1: ifb%a==0: print('bisnotprime') break a=a-1else:#沒有執(zhí)行break,則執(zhí)行else print('bisprime')4.2while循環(huán)語句——else語句

68判斷b是否為質(zhì)數(shù),就看小于b//2的所有數(shù)中,有沒有能整除b的。在這個例子中,如果有一個數(shù)滿足b除以a等于0,也就是說b有因子,b就不是質(zhì)數(shù)。那么,接下來會執(zhí)行if結(jié)構(gòu)中的print和break語句。執(zhí)行break語句之后,會跳過else子句。如果,小于b//2的所有數(shù)中,沒有一個可以整除b,b就是質(zhì)數(shù)。那么就不會執(zhí)行if結(jié)構(gòu)中的語句塊,而是執(zhí)行else子句的print語句。4.3for循環(huán)語句

69Python中的for循環(huán)通常用來遍歷有序的序列對象(如字符串,列表)內(nèi)的元素。while循環(huán)和for循環(huán)可以相互轉(zhuǎn)換,Python的for循環(huán)更常用于遍歷一個特定的序列。for循環(huán)的一般格式如下:首行會定義一個賦值目標(biāo)變量<target>,in后面跟著要遍歷的對象<object>,下面是需要重復(fù)執(zhí)行的語句塊1。同while循環(huán),for循環(huán)也有一個else子句,如果在for循環(huán)的結(jié)構(gòu)體中遇到break語句,那么就會執(zhí)行else的語句塊2。for循環(huán)也有continue語句,碰到continue語句,就忽略接下來的語句,而直接回到for循環(huán)的開頭。for<target>in<object>:<語句塊1>else:<語句塊2>4.3for循環(huán)語句

70執(zhí)行for循環(huán)時,對象<object>中的每一個元素會依次賦值給目標(biāo)<target>,然后為每個元素執(zhí)行一遍<語句塊1>。賦值目標(biāo)變量<target>可以是一個新的變量名,如果變量target是之前出現(xiàn)過的變量名,該變量則會被覆蓋。例如:#<程序:for的目標(biāo)<target>變量>i=1m=[1,2,3,4,5]deffunc():x=200forxinm:print(x);print(x);func()該程序中,雖然x的初值為200,但是在for循環(huán)中,x被覆蓋,在最后的print語句執(zhí)行時,打印出的值是5。這一點(diǎn)需要引起注意,尤其是在for語句中嵌套for語句時,如果使用相同的變量名,是很容易出錯的,而這種錯誤是不容易發(fā)現(xiàn)的。4.3for循環(huán)語句——對序列的遍歷

71在序列的遍歷時分別介紹過用for與while實現(xiàn),但在實際使用中通常使用for循環(huán)。需要注意的是,如果要更改遍歷的序列,最好方式是對序列先做一個拷貝,分片是最好的選擇。比較以下兩段程序,除了for循環(huán)的<object>變量words有細(xì)小差別外,其它完全一樣。但是運(yùn)行結(jié)果卻完全不同!左側(cè)的程序會陷入死循環(huán),因為在循環(huán)體內(nèi)對words列表進(jìn)行append操作時,每增加一個元素,將會再次對該元素進(jìn)行遍歷,而右邊程序因為使用了分片words[:],所以w遍歷完'cat','window','defenestrate'三個元素后將退出循環(huán)。#<程序:while循環(huán)改變列表1>words=['cat','window','defenestrate']forwinwords: iflen(w)>6: words.append(w)print(words)#<程序:while循環(huán)改變列表2>words=['cat','window','defenestrate']forwinwords[:]: iflen(w)>6: words.append(w)print(words)4.3for循環(huán)語句——range函數(shù)的應(yīng)用

72Python的range函數(shù)通常用來產(chǎn)生整數(shù)列表,所以range函數(shù)的外層通常有一個list函數(shù),將產(chǎn)生的整數(shù)構(gòu)成一個列表。Range函數(shù)可以根據(jù)不同的約束條件,產(chǎn)生需要的整數(shù)列表。當(dāng)range函數(shù)中只有一個參數(shù)時,會產(chǎn)生從零開始,每次加1的整數(shù)列表。例如list(range(10)),將產(chǎn)生一個列表:[0,1,2,3,4,5,6,7,8,9]。range函數(shù)中有兩個參數(shù)時,第一個為下邊界,第二個為上邊界。會產(chǎn)生兩邊界之間,且“步長”(相鄰兩整數(shù)之間,后一整數(shù)與前一整數(shù)的差值)為1的整數(shù)列表如下:list(range(3,10)),將產(chǎn)生一個列表:[3,4,5,6,7,8,9]。range函數(shù)中有三個參數(shù)時,第一個視為下邊界,第二個是上邊界,第三個視為步長。例如:list(range(-10,-100,-30)),將產(chǎn)生一個列表:[-10,-40,-70]。4.3for循環(huán)語句——range函數(shù)的應(yīng)用

73例如:現(xiàn)需要打印一個列表的所有元素及其他們的索引號。這個程序可以結(jié)合range函數(shù)和len函數(shù)實現(xiàn)。#<程序:使用range遍歷列表>L=['Python','is','strong']foriinrange(len(L)): print(i,L[i])輸出結(jié)果:0Python1is2strong第5節(jié)Python函數(shù)調(diào)用

74引言:在前一章介紹了Python函數(shù)調(diào)用的相關(guān)內(nèi)容,以及局部變量、全局變量的概念。本節(jié)將對Python函數(shù)調(diào)用中“參數(shù)的傳遞”進(jìn)行深入了解。Python進(jìn)行函數(shù)調(diào)用時,參數(shù)的傳遞都是通過賦值的方式。Python中的數(shù)據(jù)結(jié)構(gòu)有兩種類型:可變類型與不可變類型。可變類型有列表,字典等,而不可變類型有數(shù)字、字符串等。對參數(shù)的修改將會影響到可變類型的數(shù)據(jù)結(jié)構(gòu),而不會影響到不可變類型的數(shù)據(jù)結(jié)構(gòu)。引例

75這里,在調(diào)用func函數(shù)時傳入列表L,函數(shù)對參數(shù)L1的修改會直接影響到L的內(nèi)容。在前面學(xué)習(xí)Python函數(shù)調(diào)用時,明確了參數(shù)都是局部變量。那么,函數(shù)func中的對參數(shù)L1做的更改,為什么會影響到函數(shù)外面的L?#<程序:列表的append方法>deffunc(L1):L1.append(1)L=[2]func(L)print(L)輸出結(jié)果:[2,1]引例

76下面,將深入探索func函數(shù)調(diào)用時參數(shù)傳遞的原理。下圖表明了func函數(shù)調(diào)用前后,L與L1之間的映射關(guān)系。函數(shù)中的參數(shù)雖然都是局部變量,但列表做參數(shù)時,傳遞的是指針,所指向的內(nèi)容是全局變量區(qū)域,稱作heap。函數(shù)調(diào)用時,func中的列表L1和L都指向同一塊內(nèi)存區(qū)域,所以對L1的修改會影響到L,盡管L1是所謂的局部變量。引例2

77列表的append,pop,remove等方法,以及給L[i]賦值,對L[i]使用增強(qiáng)賦值等,都會修改列表L所指向的內(nèi)容,進(jìn)而對全局產(chǎn)生影響。相反,列表做一般的合并,或者使用列表的分片(即L[i:j]這種形式)都不會對全局的列表L產(chǎn)生影響。因為合并和分片操作產(chǎn)生一個新的列表,會復(fù)制原來的列表到一塊新的內(nèi)存區(qū)域。所以原來的列表不會改變!看一個對列表做合并操作的例子。#<程序:加法(+)合并列表>deffunc(L1):x=L1+[1]print(x,L1)L=[2]func(L)print(L)輸出結(jié)果:([2,1],[2])[2]引例2

78在這個例子中,列表L傳遞給func函數(shù)的參數(shù)L1,func函數(shù)在參數(shù)L1后面添加了數(shù)字1,并賦給變量x。函數(shù)調(diào)用返回后,列表L未發(fā)生變化。下圖表明了func函數(shù)調(diào)用前后,L與L1之間的映射關(guān)系:對L1做合并操作時,相當(dāng)于拷貝了一個L1到新的內(nèi)存空間,做合并之后,局部變量x指向新的內(nèi)存空間。所以,在這個例子中,全局變量L并未發(fā)生改變。引例3

79列表的分片也不會對全局的列表L產(chǎn)生影響。下面來看一個列表分片的例子。#<程序:列表分片的例子>deffunc(L1):x=L1[1:3]print(x,L1)L=[2,'a',3,'b',4]func(L)print(L)輸出結(jié)果:(['a',3],[2,'a',3,'b',4])[2,'a',3,'b',4]對L1做分片操作時,也會分配新的內(nèi)存空間,局部變量x指向新的內(nèi)存空間。所以,在分片的例子中,全局變量L也沒有發(fā)生改變。下面將給出一個關(guān)于在函數(shù)調(diào)用時,列表做參數(shù)的復(fù)雜的例子,并分析其過程。5.1L=X語句,L和X指向堆(heap)的同一處

80#<程序:L=X>defF0():X=[9,9]L.append(8)X=[1,2,3]L=XF0()print("X=",X,"L=",L)上述程序執(zhí)行到F0()函數(shù)調(diào)用前,列表X和L在內(nèi)存中的存儲如左圖所示。L=X語句使得L和X指向堆(heap)的同一處。在棧中的X和L都只是一個指針,它們的具體內(nèi)容存儲在堆上。執(zhí)行語句a之后,列表X和L在內(nèi)存中的存儲如右圖所示。由于L和X指向堆的同一處,F(xiàn)0中L.append(8)語句修改了L,也會修改全局的X。輸出結(jié)果:X=[1,2,3,8]L=[1,2,3,8]5.2L=X[:]使得L與X指向堆的不同處

81#<程序:L=X[:]>defF0():X=[9,9]L.append(8)X=[1,2,3];L=X[:]F0() print("X=",X,"L=",L)上述程序執(zhí)行到F0()函數(shù)調(diào)用時,列表X和L在內(nèi)存中的存儲如圖4.5(1)所示。L=X[:]是重新分配了一塊內(nèi)存空間,并復(fù)制x的內(nèi)容到這塊新的內(nèi)存空間,所以L和X指向堆的不同地方。執(zhí)行語句b之后,列表X和L在內(nèi)存中的存儲如圖4.5(2)所示。L和X指向堆的不同處,F(xiàn)0中L.append(8)語句修改了L,但不會修改X。后來壓入的列表X是局部變量。輸出結(jié)果:X=[1,2,3]L=[1,2,3,8]5.3return(L)返回L的指針

82#<程序:返回(return)列表>defF1():L=[3,2,1]return(L)L=F1()print("L=",L)如圖,該段程序調(diào)用函數(shù)F1,F(xiàn)1中定義了一個局部變量L并返回。返回的是局部變量L的指針,此時,全局變量L與返回的局部變量L指向同一處。輸出結(jié)果:L=[3,2,1]優(yōu)美而健康的程序

83前面講完基本概念后,我們將要講如何編寫優(yōu)美而健康的程序。強(qiáng)烈建議同學(xué),在函數(shù)里要盡量少用全局變量,要用參數(shù)來傳遞信息。參數(shù)是列表時要特別注意!因為參數(shù)是列表時,所傳遞的只是個指針,雖然這個指針是局部變量,但是內(nèi)容是存在全局的地址上,所以這個列表是個“假”局部變量,本質(zhì)還是全局的。假如這個函數(shù)設(shè)計的本意不是要將參數(shù)列表內(nèi)容改變時,最好在函數(shù)一開始時就產(chǎn)生個全新的拷貝。例如,defF(L):L1=L[:]。這樣在L1上操作,就不會影響到L的內(nèi)容了。5.2L=X[:]使得L與X指向堆的不同處

84#<程序:L做函數(shù)參數(shù)傳遞>defF2(L): L=[2,1] return(L)defF3(L): L.append(1)L[0]=0L=[3,2,1]L=F2(L);print("L=",L)F3(L);print("L=",L)輸出結(jié)果:L=[2,1]L=[0,1,1]如上圖,當(dāng)調(diào)用函數(shù)F2時,傳入全局變量L。F2的L=[3,2,1]將L指向的內(nèi)容修改為[2,1]。如上圖,當(dāng)調(diào)用函數(shù)F3,傳入全局變量L。F2的L.append(1)將L指向的內(nèi)容修改為[0,1,1]。第6節(jié)Py

溫馨提示

  • 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

提交評論