版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第9章字符串與文件處理Python程序設(shè)計第9章字符串與文件程序的輸入和輸出通常都涉及字符串處理,Python提供了一些在數(shù)字和字符串間執(zhí)行轉(zhuǎn)換的運(yùn)算符。字符串是字符序列,而列表可以包含任何類型的值,可以用內(nèi)置的序列操作來處理字符串和列表。字符串格式化方法(format)可用于生成格式良好的輸出。第9章字符串與文件這一章中還介紹了文本、字節(jié)、文件,這些都是數(shù)據(jù)處理的基礎(chǔ)知識。文件接口不只是針對硬盤里的文件,也包括各種電腦外部設(shè)備的存取以及網(wǎng)絡(luò)傳輸。幾乎任何內(nèi)容都以文件的形式存放在文件系統(tǒng)里,包括硬盤、鍵盤、USB、I/O接口等。字符串的概念1文件對話框4字符串格式化2文件處理3目錄字符串?dāng)?shù)據(jù)類型字符串轉(zhuǎn)換函數(shù)簡單字符串處理字符串表示函數(shù)輸入/輸出操作9.1定義字符串9.1
定義字符串除了list(列表)與tuple(元組)以外,基本的序列類型還有str(字符串)。str也是容器,是不可變類型,含有一個個字節(jié),如同把字節(jié)串接起來,所以稱為字符串(string)。Python中并沒有“字符(character)”類型,需要時可使用含有一個字節(jié)的字符串。str是以抽象的字節(jié)為元素的Unicode字符串,而不是以固定數(shù)目的二進(jìn)制位為單位,至于字節(jié)數(shù)據(jù)則由新類型bytes負(fù)責(zé)。9.1.1字符串?dāng)?shù)據(jù)類型在程序中,文本由字符串?dāng)?shù)據(jù)類型表示,視為一個字符序列??梢杂靡枌⒁恍┳址ㄆ饋硇纬勺址置媪?。Python還允許字符串由單引號(')分隔,在使用時一定要配對。字符串也可以保存在變量中。下面的例子說明了字符串字面量的兩種形式:>>>str1="Hello">>>str2='spam'>>>print(str1,str2)Hellospam>>>type(str1)<class'str'>>>>type(str2)<class'str'>9.1.1字符串?dāng)?shù)據(jù)類型我們已經(jīng)知道input函數(shù)返回用戶鍵入的任何字符串對象。這意味著如果你希望得到的是一個字符串,就可以使用其“原始”(未轉(zhuǎn)換)形式的輸入。例如: >>>firstName=input("請輸入你的名字:")
請輸入你的名字:xiaoming >>>print("Hello",firstName) Helloxiaoming這里我們用變量保存用戶名字,然后用該變量將名字打印出來。9.1.1字符串?dāng)?shù)據(jù)類型字符串是一個字符序列。為訪問組成字符串的單個字符,在Python中可以通過“索引”操作來完成。我們可以認(rèn)為字符串中的位置是被左起編號的,開始為0。下圖用字符串“HelloBob”加以說明。字符串“HelloBob”的索引9.1.1字符串?dāng)?shù)據(jù)類型在字符串表達(dá)式中,索引用于訪問字符串中的特定字符的位置,一般形式是<string>[<expr>],其中表達(dá)式的值確定了從字符串中選擇哪個字符。例如:>>>greet="HelloBob">>>greet[0]'H'>>>print(greet[0],greet[2],greet[4])Hlo>>>x=8>>>print(greet[x-2])B9.1.1字符串?dāng)?shù)據(jù)類型在n個字符的字符串中,因?yàn)樗饕龔?開始,所以最后一個字符的位置是n-1,注意到字符串對象與實(shí)際打印輸出之間的差異。在交互中,Pythonshell通過將字符串的值放在單引號中來顯示值,由此告訴我們當(dāng)前看的是一個字符串對象。實(shí)際打印字符串時,不會在字符序列周圍添加引號,只是得到包含在字符串中的文本??梢允褂秘?fù)索引,從字符串的右端索引,這對于獲取字符串的最后一個字符特別有用。>>>greet[-1]'b'>>>greet[-3]'B'9.1.1字符串?dāng)?shù)據(jù)類型索引返回包含較大字符串中單個字符的字符串,也可以從字符串中訪問連續(xù)的字符序列或“子字符串”,這是通過“切片”操作來實(shí)現(xiàn)的。下面是一些切片:>>>greet[0:3]'Hel'>>>greet[5:9]'Bob'>>>greet[:5]'Hello'>>>greet[5:]'Bob'>>>greet[:]'HelloBob'9.1.1字符串?dāng)?shù)據(jù)類型最后三個示例表明,如果切片中的任何一個表達(dá)式缺失,字符串的開始和結(jié)束都是假定的默認(rèn)值,最后的表達(dá)式實(shí)際上給出了整個字符串?;镜淖址僮骺偨Y(jié)如表9-1所示。表9-1Python字符串操作9.1.1字符串?dāng)?shù)據(jù)類型若字符串內(nèi)含有特殊字節(jié),例如新行、TAB以及難以打出來的字節(jié),可使用反斜線“\”作為轉(zhuǎn)義符號(又稱跳脫字節(jié),跳脫碼),后面跟一串以一定格式標(biāo)示的字節(jié),形成轉(zhuǎn)義字符串,分別代表不同的特殊字節(jié)(見表9-2)。表9-2轉(zhuǎn)義字符串>>>'How\'sgoing?' #單引號內(nèi)以“\”轉(zhuǎn)義單引號"How'sgoing?">>>s='abc\'def\"ghi' #轉(zhuǎn)義單引號與雙引號>>>print(s)abc'def"ghi>>>s='abc\tdef\n' #轉(zhuǎn)義TAB與換行>>>s'abc\tdef\n'9.1.1字符串?dāng)?shù)據(jù)類型>>>print(s)abcdef #有個TAB #有個換行>>>print('abc\newlinedef') #注意,“\n”會變成換行AbcEwlinedef>>>'\x61\x62\x63\x09\x64' #以十六進(jìn)制數(shù)值表示'abc\td''abc\td'>>>'\141\142\143\011\144' #以八進(jìn)制數(shù)值表示'abc\td'>>>'abc\qdef' #不正確的轉(zhuǎn)義字符串'abc\\qdef' #反斜線“\”會被保留9.1.1字符串?dāng)?shù)據(jù)類型9.1.1字符串?dāng)?shù)據(jù)類型如果字符串跨越多行,使用三重引號較為方便,三重引號之間的換行與引號都無須轉(zhuǎn)義;但若需要輸出三個連續(xù)引號,還是需要轉(zhuǎn)義。當(dāng)想要在程序代碼里置入大量HTML、XML、JSON這樣的標(biāo)示語言內(nèi)容時,就適合使用三重引號。>>>s='''abcdef...ghijklmno #之間各夾一個TAB...pqr\t\nstu #也可轉(zhuǎn)義TAB與換行...vw'''>>>s'abcdef\nghi\tjkl\tmno\npqr\t\nstu\nvw'9.1.1字符串?dāng)?shù)據(jù)類型>>>print(s) #輸出來的樣子abcdefghijklmnopqrstuvw>>>'''abc\'\'\'def''' #每個引號都轉(zhuǎn)義"abc'''def">>>'''abc''\'def''' #只轉(zhuǎn)義一個引號,"abc'''def" #只要沒有連續(xù)三個引號即可9.1.1字符串?dāng)?shù)據(jù)類型9.1.1字符串?dāng)?shù)據(jù)類型因?yàn)榉葱本€“\”被當(dāng)作轉(zhuǎn)義字節(jié),有時候字符串中須含有大量反斜線時,就不太方便,此時可在開頭引號前加上“r”或“R”,代表raw(原始)之意,其作用是取消大部分的轉(zhuǎn)義字符串,但仍可轉(zhuǎn)義引號。當(dāng)需要表達(dá)Windows的路徑時,可使用此種表達(dá)方式。>>>'\n' #一個字節(jié),換行'\n'>>>r'\n' #兩個字節(jié),反斜線與換行'\\n'>>>"\"" #一個字節(jié),雙引號'"'>>>r'\\' #兩個字節(jié),都是反斜線'\\\\'>>>r"\"" #仍可轉(zhuǎn)義引號,但反斜線也會被留下'\\"'9.1.1字符串?dāng)?shù)據(jù)類型>>>print('C:\newfolder\today') #\n與\t都是轉(zhuǎn)義字符串C:ewfolderoday>>>print(r'C:\newfolder\today') #加上rC:\newfolder\today>>>r'C:\' #不能以“\'”結(jié)尾,意義不清楚,
File"<stdin>",line1 #結(jié)尾引號被反斜線轉(zhuǎn)義掉了
r'C:\'^SyntaxError:EOLwhilescanningstringliteral9.1.1字符串?dāng)?shù)據(jù)類型>>>s=r'abc\#加上r后,“反斜線”與“換行”代表原來的字節(jié)...defghi' #不代表延續(xù)到下一行>>>s #s中有反斜線與換行'abc\\\ndefghi'9.1.1字符串?dāng)?shù)據(jù)類型9.1.1字符串?dāng)?shù)據(jù)類型以字面值的方式建立字符串對象,之后便可運(yùn)用內(nèi)置函數(shù)、序列類型共同的操作動作、字串特有的方法、各種模塊來操作字符串,因?yàn)樽址遣豢勺儗ο?,所以在操作運(yùn)算之后,都會得到新的字符串對象。9.1.2字符串轉(zhuǎn)換函數(shù)Python中,為了方便對字符串中的字母進(jìn)行大小寫轉(zhuǎn)換,提供了幾個方法,分別是title()、lower()、upper()、capitalize()和swapcase()。
upper()全轉(zhuǎn)換成大寫
lower()全轉(zhuǎn)換成小寫
title()標(biāo)題首字母大寫
swapcase()大小寫字母互換
capitalize()首字母大寫,其余全部小寫9.1.2字符串轉(zhuǎn)換函數(shù)例如,下面是幾個簡單的代碼:str="chengxuitquan"print(str.upper()) #把所有字符中的小寫字母轉(zhuǎn)換成大寫字母print(str.lower()) #把所有字符中的大寫字母轉(zhuǎn)換成小寫字母print(str.title()) #把每個單詞的第一個字母轉(zhuǎn)化為大寫,其余小寫print(str.capitalize()) #把第一個字母轉(zhuǎn)化為大寫字母,其余小寫print(str.swapcase()) #把大小寫字母互換運(yùn)行結(jié)果是:CHENGXUITQUANchengxuitquanChengXuItQuanChengxuitquanCHENGXUITQUAN9.1.3簡單字符串處理函數(shù)許多計算機(jī)系統(tǒng)使用用戶名和密碼組合來認(rèn)證系統(tǒng)用戶。系統(tǒng)管理員必須為每個用戶分配唯一的用戶名,用戶名通常來自用戶的實(shí)際姓名。以英文用戶名為例,一種生成用戶名的方案是使用用戶的第一個首字母,然后是用戶姓氏的最多七個字母。利用這種方法,ZaphodBeeblebrox的用戶名將是“zbeebleb”,而JohnSmith就是“jsmith”。下面,我們按照基本的輸入、處理、輸出模式編寫一個程序,讀取一個人的名字并計算相應(yīng)的用戶名。為簡潔起見,在程序中包含算法的概要作為注釋?!境绦?qū)嵗?-1】生成用戶名的簡單字符串處理程序。#username.pydefmain():print("這個程序生成計算機(jī)用戶名。\n")#獲取用戶的名字和姓氏
first=input("請輸入您的名字(全字母小寫):")last=input("請輸入您的姓氏(全字母小寫):")#將第一個首字母連接到姓氏的7個字符
uname=first[0]+last[:7]#輸出用戶名
print("您的用戶名是:",uname)main()9.1.3簡單字符串處理函數(shù)9.1.3簡單字符串處理函數(shù)這個程序首先利用input從用戶處獲取字符串,然后組合使用索引、切片和連接等方法來生成用戶名。在第一個print語句中將換行符(\n)放在字符串的末尾,用以輸出一個空行。這是一個簡單的技巧,輸出一些額外的空白可以更好看一些。9.1.3簡單字符串處理函數(shù)再來看一個例子。假設(shè)要打印給定月份數(shù)對應(yīng)的月份縮寫。程序的輸入是一個代表一個月份(1~12)的int數(shù)值,輸出的是相應(yīng)月份的縮寫。例如輸入3,則輸出應(yīng)為Mar,即3月。為此,必須根據(jù)用戶給出的數(shù)字,確定一種合適的月份輸出。這里可以通過一些巧妙的字符串切片來編寫程序,基本思想是將所有月份名稱存儲在一個大字符串中: months="JanFebMarAprMayJunJulAugSepOctMovDec"通過切出適當(dāng)?shù)淖幼址畞聿檎姨囟ǖ脑路?,訣竅是計算在哪里切片。由于每個月由三個字母表示,如果知道一個給定的月份在字符串中的開始位置,就可以很容易地提取縮寫: MonthAbbrev=months[pos:pos+3]這將獲得從pos指示位置開始的長度為3的子串。9.1.3簡單字符串處理函數(shù)每個月份的位置都是3的倍數(shù),而字符串索引從0開始。這樣,為了得到正確的倍數(shù),我們從月數(shù)中減去1,然后乘以3。所以對于1,得到(1–1)*3=0*3=0,對于12,我們有(12–1)*3=11*3=33?!境绦?qū)嵗?-2】打印給定月份數(shù)字對應(yīng)的月份縮寫,其中注釋記錄了程序的算法。#month.pydefmain():#months用作查找表
months="JanFebMarAprMayJunJulAugSepOctNovDec"n=int(input("輸入月份編號(1-12):"))#以月為單位計算月份n的起始位置
pos=(n-1)*3#從幾個月抓取適當(dāng)?shù)那衅?/p>
monthAbbrev=months[pos:pos+3]#打印結(jié)果
print("月份縮寫是",monthAbbrev+".")main()9.1.3簡單字符串處理函數(shù)9.1.3簡單字符串處理函數(shù)程序分析:該程序的最后一行利用字符串連接,將句點(diǎn)放在月份縮寫的末尾。下面是程序輸出的示例:輸入月份編號(1-12):4月份縮寫是Apr.想一想:這個例子使用“字符串作為查找表”方法,它有一個弱點(diǎn),即僅當(dāng)子串都有相同的長度(在本例中是3)時才有效。假設(shè)我們希望編寫一個程序,輸出給定數(shù)字的完整月份名稱,該如何實(shí)現(xiàn)呢?9.1.4字符串表示函數(shù)在計算機(jī)內(nèi)部,數(shù)字以二進(jìn)制符號(0和1組成的序列)存儲,計算機(jī)CPU中包含有用這種表示方法進(jìn)行運(yùn)算的電路,文本信息也以完全相同的方式表示。在底層,計算機(jī)操作文本和進(jìn)行數(shù)字運(yùn)算是完全一樣的。如今的計算機(jī)系統(tǒng)主要使用ASCII(美國信息交換標(biāo)準(zhǔn)代碼)的工業(yè)標(biāo)準(zhǔn)編碼。ASCII用數(shù)字0~127來表示通常計算機(jī)鍵盤上的字符以及被稱為控制代碼的某些特殊值,用于協(xié)調(diào)信息的發(fā)送和接收。例如,大寫字母A~Z由值65~90表示,小寫字母的代碼值為97~122。ASCII編碼中缺少一些其他語言所需要的符號,為此,國際標(biāo)準(zhǔn)組織(ISO)開發(fā)了擴(kuò)展ASCII編碼。大多數(shù)現(xiàn)代系統(tǒng)正在向Unicode轉(zhuǎn)移,這是一個更大的標(biāo)準(zhǔn),旨在包括幾乎所有書面語言的字符。Python字符串支持Unicode標(biāo)準(zhǔn),因此,只要你的操作系統(tǒng)有適當(dāng)?shù)淖煮w來顯示字符,就可以處理來自任何語言的字符。9.1.4字符串表示函數(shù)Python提供了幾個內(nèi)置函數(shù),允許在字符和字符串中表示它們的數(shù)字值之間來回切換。例如ord函數(shù)返回單字符串的數(shù)字(“ordinal”)編碼,而chr相反。下面是一些交互的例子:>>>ord("a")97>>>ord("A")65>>>chr(97)'a'>>>chr(90)'z'9.1.4字符串表示函數(shù)你會注意到這些結(jié)果與字符的ASCII編碼一致。按照設(shè)計,Unicode使用的相應(yīng)代碼與ASCII最初定義的127個字符相同。但Unicode還包括更多其他的字符。例如,希臘字母pi是字符960,歐元的符號是字符8364。在計算機(jī)中,底層CPU處理固定大小的內(nèi)存。最小可尋址段通常為8位,稱為存儲器字節(jié)。單個字節(jié)可以存儲28=256個不同的值。這足以代表每個可能的ASCII字符。但是,單個字節(jié)遠(yuǎn)遠(yuǎn)不足以存儲所有10萬個可能的Unicode字符。為了解決這個問題,Unicode標(biāo)準(zhǔn)定義了將Unicode字符打包成字節(jié)序列的各種編碼方案。最常見的編碼稱為UTF-8。UTF-8是一種可變長度編碼方案,用單個字節(jié)存儲ASCII子集中的字符,但可能需要最多四個字節(jié)來表示一些更為深奧的字符。9.1.5輸入/輸出操作有些程序,即使主要不是進(jìn)行文本操作,也經(jīng)常需要用到字符串。例如,考慮一個財務(wù)分析程序,其中的某些信息(如日期)必須以字符串形式輸入。在進(jìn)行一些數(shù)字處理之后,分析的結(jié)果通常是一個格式良好的報告,包括用于標(biāo)記和解釋數(shù)字、圖表、表格和圖形的文本信息,需要字符串操作來處理這些基本的輸入和輸出任務(wù)。9.1.5輸入/輸出操作作為一個具體的例子,我們將月份縮寫程序擴(kuò)展成日期轉(zhuǎn)換。用戶輸入一個日期,例如“05/24/2020”,程序?qū)@示日期為“May24,2020”。下面是該程序的算法:以mm/dd/yyyy格式輸入日期(dateStr)將dateStr拆分為月,日和年字符串將dateStr轉(zhuǎn)換為月份數(shù)字使用月份編號查找月份名稱在MonthDay,Year中創(chuàng)建一個新的日期字符串輸出新的日期字符串可以用字符串操作在代碼中直接實(shí)現(xiàn)算法的前兩行:dateStr=input("輸入日期(mm/dd/yyyy):")monthStr,dayStr,yearStr=datestr.split("/")9.1.5輸入/輸出操作這里得到一個字符串的日期,并以斜杠分隔。然后利用同時賦值,將三個字符串的列表“分拆”到變量monthStr、dayStr和yearStr中。接下來是將monthStr轉(zhuǎn)換為適當(dāng)?shù)臄?shù)字(使用int),然后用該值查找正確的月份名稱。下面是代碼:months=["January","February","March","April","May","June","July","August","September","October","November","December"]monthStr=months[int(monthStr)-1]使用索引表達(dá)式int(monthStr)-1是因?yàn)榱斜硭饕龔?開始。程序的最后一步是以新格式拼出日期。注意程序中如何使用連接實(shí)現(xiàn)緊跟日期的逗號。 print("轉(zhuǎn)換的日期是:",monthStr,dayStr+",",yearStr)【程序?qū)嵗?-3】將日期格式“mm/dd/yyyy”轉(zhuǎn)換為“月,日,年”。#dateconvert.pydefmain():#得到日期
dateStr=input("輸入日期(mm/dd/yyyy):")#分成組件
monthStr,dayStr,yearStr=dateStr.split("/")9.1.5輸入/輸出操作#將monthStr轉(zhuǎn)換為月份名稱
months=["January","February","March","April","May","June","July","August","September","October","November","December"]monthStr=months[int(monthStr)-1]#輸出結(jié)果以月日年格式顯示
print("轉(zhuǎn)換的日期是:",monthStr,dayStr+",",yearStr)main()9.1.5輸入/輸出操作9.1.5輸入/輸出操作程序分析:運(yùn)行時,輸出如下所示:輸入日期(mm/dd/yyyy):05/24/2020轉(zhuǎn)換的日期是:May24,2020我們常常也需要將數(shù)字轉(zhuǎn)成字符串。在Python中,大多數(shù)據(jù)類型可以用str函數(shù)轉(zhuǎn)換為字符串,例如:>>>str(500)'500'>>>value=3.14>>>str(Value)'3.14'>>>print("Thevalueis",str(value)+".")Thevalueis3.14.9.1.5輸入/輸出操作注意最后一個例子。通過將值轉(zhuǎn)換為字符串,可以用字符串連接在句子的尾處放置句點(diǎn)。如果不先將值轉(zhuǎn)換為字符串,Python會將“+”解釋為數(shù)字運(yùn)算產(chǎn)生錯誤,因?yàn)椤?”不是數(shù)字。現(xiàn)在有了一套完整的操作,用于在各種Python數(shù)據(jù)類型之間轉(zhuǎn)換值(見表9-3)。表9-3類型轉(zhuǎn)換函數(shù)9.1.5輸入/輸出操作將數(shù)字轉(zhuǎn)換為字符串的一個常見原因,是字符串操作可用于控制值的打印方式。例如,執(zhí)行日期計算的程序必須將月、日和年作為數(shù)字操作,而格式化輸出時這些數(shù)字將被轉(zhuǎn)換回字符串。9.2
字符串格式化9.2
字符串格式化基本的字符串操作對于簡單格式的格式化輸出是有用的,但是構(gòu)建復(fù)雜輸出時就可能很麻煩,為此Python提供了一個強(qiáng)大的字符串格式化操作?!境绦?qū)嵗?-4】以外幣(美元)為例,一個計算美元零錢的程序。#change.pydefmain():print("貨幣兌換")print()print("請輸入每種硬幣類型的數(shù)量。")quarters=eval(input("25分:"))dimes=eval(input("10分:"))nickels=eval(input("5分:"))pennies=eval(input("1分:"))total=quarters*.25+dimes*.10+nickels*.05+pennies*.01print()print("你兌換的總值是",total)main()9.2
字符串格式化9.2
字符串格式化程序分析:下面是上述程序的運(yùn)行結(jié)果:貨幣兌換請輸入每種硬幣類型的數(shù)量。25分:610分:05分:01分:0你兌換的總值是1.59.2
字符串格式化注意,最終值是以一位小數(shù)的形式給出的,這可以通過更改程序的最后一行來解決,例如:print("你的兌換總值是${0:0.2f}".format(total))現(xiàn)在程序打印以下消息:
你的兌換總值是$1.50其中,format方法是Python內(nèi)置的字符串方法,它用字符串作為模板,值作為參數(shù)提供,插入到該模板中,從而形成一個新的字符串。字符串格式化的形式為: <template-string>.format(<values>)模板字符串中的花括號({})標(biāo)記出“插槽”,提供的值將插入該位置?;ɡㄌ栔械男畔⒅甘静宀壑械闹狄约爸祽?yīng)如何格式化。9.2
字符串格式化Python格式化操作符非常靈活,通常插槽說明總是具有以下形式: {<index>:<format-specifier>}即:{<索引>:<格式說明符>}<索引>告訴哪個參數(shù)被插入到插槽中。插槽描述的索引部分是可選的,省略索引時,參數(shù)僅以從左到右的方式填充到插槽中。索引從0開始。上面的例子中有一個插槽,索引0用于表示第一個(也是唯一的)參數(shù)插入該插槽。冒號后的描述部分指定插入插槽時該值的外觀。再次回到示例,格式說明符為0.2f,此說明符的格式為<寬度>.<精度><類型>。<寬度>指明值應(yīng)占用多少“空間”。如果值小于指定的寬度,則用額外的字符填充(默認(rèn)值是空格)。<精度>為2,告訴Python將值舍入到兩個小數(shù)位。最后,<類型>字符f表示該值應(yīng)顯示為定點(diǎn)數(shù)。這意味著,將始終顯示指定的小數(shù)位數(shù),即使它們?yōu)?。9.2
字符串格式化對格式說明符的完整描述較難理解,最簡單的模板字符串只是指定在哪里插入?yún)?shù)。下面,我們通過幾個例子來熟悉它。>>>"Hello{0}{1},youmayhavewon${2}".format("Mr.","Smith",10000)‘HelloMr.Smith,youmayhavewon$10000.’(您好史密斯先生,您可能贏得$10000。)通常,我們想要控制一個數(shù)學(xué)值的寬度和精度:>>>"Thisint,{0:5},wasplacedinafieldofwidth5".format(7)'Thisint,7,wasplacedinafieldofwidth5.'(“這個整數(shù)7放置在寬度為5的字段中。”)>>>"Thisint,{0:10},wasplacedinafieldofwidth10".format(7)'Thisint,7,wasp1acedinafieldofwidth10'9.2
字符串格式化>>>"Thisfloat,{0:10.5},haswidth10andprecision5".format(3.1415926)'Thisfloat,3.1416,haswidth10andprecision5'>>>"Thisfloat,{0:10.5f},isfixedat5decimalplaces".format(3.1415926)'Thisfloat,3.14159,isfixedat5decimalplaces'9.2
字符串格式化>>>"Thisfloat,{0:0.5},haswidth0andprecision5".format(3.1415926)'Thisfloat,3.1416,haswidth0andprecision5'>>>"Compare{0}and{0:0.20}".format(3.14)'Compare3.14and3.14000000000001243'9.2
字符串格式化9.2
字符串格式化對于正常(非定點(diǎn))浮點(diǎn)數(shù),精度指明要打印的有效數(shù)字的個數(shù)。對于定點(diǎn)(由指定符末尾的f表示),精度表示小數(shù)位數(shù)。在最后一個示例中,相同的數(shù)字以兩種不同的格式打印出來。一般來說,Python只顯示一個接近的、舍入的浮點(diǎn)型。使用顯式格式化可以查看到完整結(jié)果,直到最后一位。9.2
字符串格式化默認(rèn)情況下數(shù)值是右對齊的,而字符串在其字段中是左對齊的。通過在格式說明符的開頭包含顯式調(diào)整字符,可以更改默認(rèn)行為。對于左、右和中心對齊,所需的字符分別為<、>和^。>>>"左對齊:{0:<5}".format("嗨!")'左對齊:嗨!'>>>"右對齊:{0:>5}".format("嗨!")'右對齊:嗨!'>>>"居中:{0:^5}".format("嗨!")'居中:嗨!'9.2
字符串格式化假設(shè)我們?yōu)橐患毅y行編寫一個計算機(jī)系統(tǒng)。你的客戶得知收費(fèi)“非常接近107.56美元”,恐怕不會太高興。顯然人們希望銀行的記錄是精確的。即使給定值中的誤差量非常小,因?yàn)槿绻M(jìn)行大量計算,小誤差也可能導(dǎo)致誤差累積成真實(shí)的金額。較好的方法是確保程序用準(zhǔn)確的值來表示錢。我們可以用美分來記錄貨幣,并用int來存儲它。然后,我們可以在輸出步驟中將它轉(zhuǎn)換為美元和美分。假設(shè)我們處理正數(shù),如果total代表以分為單位的值,那么我們可以通過整數(shù)除法total//100得到美元數(shù),通過total%100得到美分?jǐn)?shù)。這兩個都是整數(shù)計算,因此會給出確切的結(jié)果。下面是更新后的程序:【程序?qū)嵗?-5】以外幣(美元)為例,一個以美分計算的總現(xiàn)金。#change2.pydefmain():print("貨幣兌換\n")print("P請輸入每種硬幣類型的數(shù)量。")quarters=int(input("25分:"))dimes=int(input("10分:"))nickels=int(input("5分:"))pennies=int(input("1分:"))9.2
字符串格式化total=quarters*25+dimes*10+nickels*5+penniesprint("你兌換的總值是${0}.{1:0>2}".format(total//100,total%100))main()9.2
字符串格式化9.2
字符串格式化程序分析:最后,打印語句被分成了兩行。通常一個語句應(yīng)該在行末結(jié)束,但有時將較長的語句分成較小的部分可能更好。print語句中的字符串格式化包含兩個插槽,一個用于美元,是int,另一個用于美分。美分插槽說明了格式說明符的另一種變化,其值用格式說明符“0>2”打印。前面的0告訴Python用0來填充字段(如果必要),確保10美元5美分這樣的值打印為10.05美元,而不是10.5美元。認(rèn)識文件打開模式多行字符串處理文件示例程序:批處理用戶名9.3文件處理9.3
文件處理字處理是字符串?dāng)?shù)據(jù)的應(yīng)用程序。所有字處理程序都有一個關(guān)鍵特征,即能夠保存和讀取文檔用作磁盤文件。文件輸入和輸出實(shí)際上是另一種形式的字符串處理。9.3.1認(rèn)識文件首先請?jiān)谖淖志庉嬈鬈浖墟I入如下內(nèi)容,將文件取名為test.txt,然后與下面的程序文件放在同一個目錄里。【程序?qū)嵗?-6】測試用文檔(test.txt)。HelloPython!Howareyou?abc1239.3.1認(rèn)識文件【程序?qū)嵗?-7】打開文件。#test.pyfin=open('test.txt') #打開文件print(fin.readline()) #讀取一行文字并輸出forlineinfin: #迭代每一行
print(line) #輸出fin.close() #關(guān)閉9.3.1認(rèn)識文件9.3.1認(rèn)識文件程序分析:程序?qū)⒆x取并輸出文檔內(nèi)容。在存取文件時必須先“打開”,得到代表該文件的對象?n,透過它所提供的接口來存取文件內(nèi)容,例如方法readline可讀取一行文字,且此對象符合可迭代項(xiàng)抽象類型,所以可交給迭代協(xié)定的接收方(例如此例中的for循環(huán)),不斷地拿出文件內(nèi)容的“下一行”,直到文件結(jié)束。最后應(yīng)調(diào)用文件對象的方法close做“關(guān)閉”的動作,因?yàn)榇蜷_文件會占用系統(tǒng)資源,應(yīng)做好清理收尾的工作。使用print(line)輸出一行時,除了輸出文件每一行結(jié)尾的“新行”字節(jié),print缺省還會再輸出一個新行字節(jié),所以輸出時多了一行空白行,可以用“print(line,end='')”改為輸出空字符串。9.3.2打開模式調(diào)用open時,第一個參數(shù)以字符串指定欲打開文件的路徑與文件名,第二個參數(shù)以字符串指定“模式”,缺省為讀取模式與文本模式,所以open('test.txt')等同于open('test.txt','r'),也等同于open('test.txt','rt'),其中r代表讀取模式,t代表文字模式(參見表6-4)。9.3.2打開模式表9-4文件打開模式9.3.2打開模式下面程序段可復(fù)制文件test.txt的內(nèi)容到新文件(testw.txt),以w模式建立新文件,調(diào)用方法write寫入。fin=open('test.txt')fw=open('testw.txt','w') #w,寫入模式forlineinfin:print(line)fout.write(line) #調(diào)用write方法寫入數(shù)據(jù)fin.close()fout.close()9.3.2打開模式文件對象的方法readline可讀出一行,readlines則讀出每一行并放在列表里返回,所以也可使用“forlinein?n.readlines()”,但這么做會一次載入文件的全部內(nèi)容,再進(jìn)行迭代,效率較低。9.3.3多行字符串文件是存儲在輔助存儲器(通常是磁盤驅(qū)動器)上的數(shù)據(jù)序列。文件可以包含任何數(shù)據(jù)類型,但最簡單的文件是文本文件。文本文件可以被人閱讀和理解,可以使用通用文本編輯器(諸如IDLE)和字處理程序來創(chuàng)建和編輯。Python中的文本文件可以非常靈活,因?yàn)樗苋菀自谧址推渌愋椭g轉(zhuǎn)換。可以將文本文件看成是一個(可能很長的)字符串,恰好存儲在磁盤上。當(dāng)然,典型的文件通常包含多于一行的文本。特殊字符或字符序列用于標(biāo)記每行的結(jié)尾。Python為我們處理不同的行結(jié)束標(biāo)記約定,只要求使用“\n”來表示換行符即可。9.3.3多行字符串我們來看一個具體的例子,假設(shè)在文本編輯器中鍵入以下行:HelloWorldGoodbye32如果存儲到文件,會得到以下字符序列: Hello\nWorld\n\nGoodbye32\n9.3.3多行字符串在得到的文件/字符串中,空行變成一個換行符,這就像我們將換行字符嵌入到輸出字符串,用一個打印語句生成多行輸出一樣。上面例子的交互式打印結(jié)果如下:>>>print("Hello\nWorld\n\nGoodbye32\n")HelloWorldGoodbye32>>>如果只是在shell中對一個包含換行符的字符串求值,將再次得到嵌入換行符的表示形式:>>>"Hello\nWorld\n\nGoodbye32\n"'Hello\nWorld\n\nGoodbye32\n'只有當(dāng)打印字符串時,特殊字符才會影響字符串的顯示方式。9.3.4處理文件(1)一次性讀取。例如想要讀取txt小說(為簡化,txt文件中只包含一段文字):file='novel.txt'withopen(file)asfile_object:contents=file_object.read()print(contents)運(yùn)行結(jié)果:Itisatruthuniversallyacknowledged,thatasinglemaninpossessionofagoodfortune,mustbeinwantofawife.要使用文件,就必須先打開它,所以這里使用了函數(shù)open()。函數(shù)open()接受一個參數(shù):即要打開的文件路徑。如果只有文件名,那么Python會在當(dāng)前執(zhí)行文件的所在目錄來查找指定的文件。9.3.4處理文件關(guān)鍵字with會在程序不再需要訪問文件或出現(xiàn)異常的情況下關(guān)閉文件,通常只管打開文件使用它即可。9.3.4處理文件(2)文件路徑。函數(shù)open()接收的參數(shù)如果只有文件名,那么Python會在當(dāng)前執(zhí)行的.py文件所在的目錄中查找文件。也可以提供文件路徑,讓Python到指定的文件目錄中去查找所需要的文件。相對路徑語法形如: withopen('xxx\novel.txt')asfile_object:一般來說,在Windows系統(tǒng)中,在文件路徑中使用反斜杠(“\”),Linux與OS使用的是斜杠(“/”)。實(shí)際測試,在Windows系統(tǒng)中,斜杠與反斜杠都支持。當(dāng)然也可以使用絕對路徑。如果使用的是絕對路徑,那么在Windows系統(tǒng)中,文件路徑必須使用反斜杠。形如: withopen('F:/python_projects/xxx/novel.txt')asfile_object:因?yàn)榻^對路徑一般較長,所以將其存儲在變量中,然后再傳入open()函數(shù)。9.3.4處理文件(3)逐行讀取。可以對文件對象使用for循環(huán),逐行讀取文件內(nèi)容。withopen(file)asfile_object:forline_contentinfile_object:print(line_content.rstrip())運(yùn)行結(jié)果與之前的“一次性讀取”示例結(jié)果相同。在txt文件中,每行的末尾都存在一個看不見的換行符。為了去除這些多余的空白行,可以使用了rstrip()函數(shù),這會刪除string字符串末尾的空格。9.3.4處理文件(4)在with外訪問使用關(guān)鍵字with時,open()函數(shù)所返回的文件對象,只能在with代碼塊中使用。如果需要在with代碼塊之外訪問文件的內(nèi)容,那么可以在with代碼塊之內(nèi),將文件中的各行內(nèi)容存儲在列表變量中,然后就可以在with代碼塊之外,通過該列表變量訪問文件內(nèi)容。withopen(file)asfile_object:contents=file_object.readlines()content_str=''forcontentincontents:content_str+=contentprint('content_str='+content_str)print('len='+str(len(content_str)))9.3.4處理文件運(yùn)行結(jié)果:content_str=Itisatruthuniversallyacknowledged,thatasinglemaninpossessionofagoodfortune,mustbeinwantofawife.len=117注意:讀取文本文件時,Python會將文件中的所有文本都解釋為字符串。如果我們需要將其中的文本解釋為數(shù)字,那么就必須使用函數(shù)int()或者float()將其轉(zhuǎn)換為整數(shù)或者浮點(diǎn)數(shù)。9.3.4處理文件Python對數(shù)據(jù)量沒有大小限制,只要系統(tǒng)內(nèi)存足夠多。文件處理的具體細(xì)節(jié)在編程語言之間有很大不同,但實(shí)際上所有語言都共享某些底層的文件操作概念。首先,我們需要一些方法將磁盤上的文件與程序中的對象相關(guān)聯(lián),這個過程稱為“打開”文件。一旦文件被打開,其內(nèi)容即可通過相關(guān)聯(lián)的文件對象來訪問。其次,我們需要一組可以操作文件對象的操作,這至少包括允許從文件中讀取信息并將新信息寫入文件的操作。最后,當(dāng)完成文件操作,它會被“關(guān)閉”,這將確保所有記錄工作都己完成,從而保持磁盤上的文件和文件對象之間的一致。9.3.4處理文件這種打開和關(guān)閉文件的思想,與字處理程序處理文件的方式密切相關(guān),但不完全相同。例如在MicrosoftWord中打開文件時,該文件實(shí)際上是從磁盤讀取并存儲到RAM中。此時,在編程意義上文件被關(guān)閉,“編輯文件”時改變的是內(nèi)存中的數(shù)據(jù),而不是文件本身。這些更改不會顯示在磁盤上的文件中,除非通知應(yīng)用程序“保存”。在Python中使用文本文件很容易。第一步是用open函數(shù)創(chuàng)建一個與磁盤上的文件相對應(yīng)的文件對象。通常文件對象立即分配給變量,如下所示: <variable>=open(<name>,<mode>)這里的name是一個字符串,它提供了磁盤上文件的名稱;mode參數(shù)是字符串“r”或“w”,這取決于我們打算從文件中讀取還是寫入文件。9.3.4處理文件例如,要打開一個名為“numbers.dat”的文件進(jìn)行讀取,可以使用如下語句: infile=open("numbers.dat","r")接著可以利用文件對象infile從磁盤讀取mumbers.dat的內(nèi)容。Python提供了三個相關(guān)操作從文件中讀取信息:<file>.read():將文件的全部剩余內(nèi)容作為單個(可能是大的、多行的)字符串返回。<file>.readline():返回文件的下一行。即所有文本,直到并包括下一個換行符。<file>.readlines():返回文件中剩余行的列表。每個列表項(xiàng)都是一行,包括結(jié)尾處的換行符?!境绦?qū)嵗?-8】用read操作將文件內(nèi)容打印到屏幕上。#printfile.pydefmain():fname=input("輸入文件名:")infile=open(fname,"r")data=infile.read()print(data)main()9.3.4處理文件9.3.4處理文件程序分析:程序首先提示用戶輸入文件名,然后打開文件以便讀取變量infile。雖然可以使用任意名稱作為變量,但這里使用infile強(qiáng)調(diào)該文件正在用于輸入。然后將文件的全部內(nèi)容讀取為一個大字符串并存儲在變量data中,打印data從而顯示內(nèi)容。readline操作可用于從文件讀取下一行。對readline的連續(xù)調(diào)用從文件中獲取連續(xù)的行,這類似于輸入,它以交互方式讀取字符,直到用戶按下回車鍵。每個對輸入的調(diào)用從用戶獲取另一行。但要記住一件事,readline返回的字符串總是以換行符結(jié)束,而input會丟棄換行符。9.3.4處理文件作為一個快速示例,這段代碼打印出文件的前五行:Infile=open(someFile,"r")foriinrange(5):line=infile.readline()print(line[:-1])請注意,利用切片去掉行尾的換行符。由于print自動跳轉(zhuǎn)到下一行(即它輸出一個行符),打印在末尾帶有顯式換行符時,將在文件行之間多加一個空行輸出?;蛘撸梢源蛴≌?,但告訴print不添加自己的換行符。 print(line,end="")9.3.4處理文件循環(huán)遍歷文件全部內(nèi)容的一種方法,是使用readlines讀取所有文件,然后循環(huán)遍歷結(jié)果列表:infile=open(someFile,"r")forlineininfile.readlines():#在這里處理一行infile.close()9.3.4處理文件當(dāng)然,這種方法的潛在缺點(diǎn)是文件可能非常大,并且一次將其讀入列表可能占用太多的RAM。有一種簡單的替代方法,Python將文件本身視為一系列行。所以循環(huán)遍歷文件的行可以直接如下進(jìn)行,每次處理文件的一行:infile=open(someFile,"r")forlineininfile:#在這里處理一行infile.close()9.3.4處理文件打開用于寫入的文件,讓該文件準(zhǔn)備好接收數(shù)據(jù)。如果給定名稱的文件不存在,就會創(chuàng)建一個新文件。注意:如果存在給定名稱的文件,Python將刪除它并創(chuàng)建一個新的空文件。寫入文件時,應(yīng)確保不要破壞以后需要的任何文件!下面是打開文件用作輸出的示例: Outfile=open("mydate.out","w")將信息寫入文本文件最簡單的方法是用已經(jīng)熟悉的print函數(shù)。要打印到文件,只需要添加一個指定文件的關(guān)鍵字參數(shù),這個行為與正常打印完全相同,只是結(jié)果被發(fā)送到輸出文件而不是顯示在屏幕上: print(…,file=<outputFile>)9.3.5示例程序:批處理用戶名如果為大量用戶設(shè)置賬戶,則該過程一般是以“批處理”方式進(jìn)行。在批處理時,程序輸入和輸出通過文件完成。下面我們設(shè)計程序用于處理一個包含名稱的文件。輸入文件的每一行將包含一個新用戶的姓和名,用一個或多個空格分隔。該程序產(chǎn)生一個輸出文件,其中包含每個生成的用戶名的行?!境绦?qū)嵗?-9】以批處理模式創(chuàng)建用戶名文件。#userfile.pydefmain():print("該程序從名稱文件創(chuàng)建用戶名文件。")#獲取文件名
infileName=input("這些名稱在哪個文件里?")outfileName=input("用戶名應(yīng)該放在哪個文件中?")9.3.5示例程序:批處理用戶名#打開該文件
infile=open(infileName,"r")outfile=open(outfileName,"w")#處理輸入文件中的每一行
forlineininfile:#從行中獲取名字和姓氏
first,last=line.split()9.3.5示例程序:批處理用戶名#建立用戶名
uname=(first[0]+last[:7]).lower()#將其寫入輸出文件
print(uname,file=outfile)#關(guān)閉兩個文件
infile.close()outfile.close()print("用戶名已經(jīng)寫入",outfileName)main()9.3.5示例程序:批處理用戶名9.3.5示例程序:批處理用戶名這個程序中同時打開兩個文件,一個用于輸入(infile),一個用于輸出(outfile)。另外,當(dāng)創(chuàng)建用戶名時,使用了字符串方法lower。請注意,該方法應(yīng)用于連接產(chǎn)生的字符串,確保用戶名全部是小寫,即使輸入名稱是大小寫混合的。【程序?qū)嵗?-10】源代碼文檔也是文件,這個程序可輸出自己。#print_self.pywithopen('print_self.py','r')asfin:forlineinfin:print(line)9.3.5示例程序:批處理用戶名9.3.5示例程序:批處理用戶名程序分析:雖然沒有指定這個程序文件本身的編碼,但因?yàn)榇蟛糠治淖志幋a系統(tǒng)都兼容于ASCII,若文件內(nèi)容只有ASCII字節(jié),存儲后的字節(jié)數(shù)據(jù)應(yīng)相同,所以這個例子可正常無誤地執(zhí)行。9.4
文件對話框9.4
文件對話框使用文件操作程序經(jīng)常出現(xiàn)一個問題,即如何指定要使用的文件。如果數(shù)據(jù)文件與程序位于同一目錄(文件夾),那么只需鍵入正確的文件名稱。當(dāng)沒有其他信息時,Python將在“當(dāng)前”目錄中查找文件。然而,有時很難知道文件的完整名稱是什么。大多數(shù)操作系統(tǒng)使用具有類似<name>.<type>形式的文件名,其中type部分是描述文件包含什么類型數(shù)據(jù)的短擴(kuò)展名(三個或四個字母)。例如“users.txt”文件,其中的“.txt”擴(kuò)展名表示是文本文件。但一些操作系統(tǒng)(如Windows)在默認(rèn)情況下只顯示在點(diǎn)之前的部分名稱,所以很難找出完整的文件名。9.4
文件對話框當(dāng)文件存在于當(dāng)前目錄之外的某處時,情況更加困難。文件處理程序可能用于輔助存儲器中任何位置存儲的文件。為了找到這些文件,必須指定完整路徑。在Windows系統(tǒng)上,帶有路徑的完整文件名可能如下所示: c:\users\Documents\PythonPrograms\users.txt大多數(shù)用戶甚至可能不知道如何找出其系統(tǒng)上任何給定文件的“完整路徑+文件名”。這個問題的解決方案是允許用戶可視地瀏覽文件系統(tǒng),并導(dǎo)航到特定的目錄/文件。向用戶請求打開或保存文件名是許多應(yīng)用程序的常見任務(wù),底層操作系統(tǒng)通常提供一種標(biāo)準(zhǔn)的、熟悉的方式來執(zhí)行此操作。通常的技術(shù)包括對話框,它允許用戶使用鼠標(biāo)在文件系統(tǒng)中點(diǎn)擊并且選擇或鍵入文件的名稱。標(biāo)準(zhǔn)Python中的tkinterGUI庫提供了一些簡單易用的函數(shù),可創(chuàng)建用于獲取文件名的對話框。9.4
文件對話框要詢問用戶打開文件的名稱,可以使用askopenfilename函數(shù),它在tkinter.filedialog模塊中。在程序的頂部,需要導(dǎo)入該函數(shù): fromtkinter.filedialogimportaskopenfilename在導(dǎo)入中使用點(diǎn)符號,是因?yàn)閠kinter是由多個模塊組成的包。在這個例子中,我們從tkinter中指定僅導(dǎo)入filedialog模塊(函數(shù)),調(diào)用askopenfilename將彈出一個系統(tǒng)對應(yīng)的文件對話框。9.4
文件對話框例如,要獲取用戶名文件的名稱,我們可以使用一行代碼,如下所示: infileName=askopenfilename()在Windows中執(zhí)行此行的結(jié)果如圖所示。該對話框允許用戶鍵入文件的名稱或用鼠標(biāo)選擇它。當(dāng)用戶單擊“打開”按鈕時,文件的完整路徑名稱將作為字符串返回并保存到變量infileName中。如果用戶單擊“取消”按鈕,該函數(shù)將簡單地返回一個空字符串。
來自askopenfilename的文件對話框9.4
文件對話框Python的tkinter提供了類似的函數(shù)asksaveasfilename用于保存文件,其用法非常相似。fromtkinter.filedialogimportasksaveasfilename…outfileName=asksaveasfilename()asksaveasfilename的示例對話框如圖所示。也可以同時導(dǎo)入這兩個函數(shù),例如:fromtkinter.filedialogimportaskopenfilename,asksaveasfilename這兩個函數(shù)還有許多可選參數(shù),可以定制得到的對話框,例如改變標(biāo)題或建議默認(rèn)文件名。
來自asksaveasfilename的文件對話框謝謝大家第10章面向?qū)ο蟪绦蛟O(shè)計Python程序設(shè)計第10章面向?qū)ο蟪绦蛟O(shè)計在本章中我們來學(xué)習(xí)面向?qū)ο缶幊蹋∣bject-OrientedProgramming、OOP)的一些重要概念。對象是結(jié)合了數(shù)據(jù)和操作的計算實(shí)體,包括相關(guān)數(shù)據(jù)的集合以及該數(shù)據(jù)的一系列操作。對象的數(shù)據(jù)存儲在實(shí)例變量中并通過方法進(jìn)行操作。每個對象都是某個類的一個實(shí)例。類定義確定了對象的屬性是什么,對象將具有什么方法。通過調(diào)用構(gòu)造函數(shù)方法創(chuàng)建實(shí)例,可以通過編寫合適的類定義來創(chuàng)建新類型的對象。面向?qū)ο蟮母拍?類的方法4類與對象2構(gòu)造函數(shù)與對象初始化3示例程序:發(fā)射炮彈6目錄類作用域510.1
面向?qū)ο蟮母拍?0.1
面向?qū)ο蟮母拍畲饲?,我們一直在使用Python內(nèi)置的數(shù)字和字符串?dāng)?shù)據(jù)類型來編寫程序。每個數(shù)據(jù)類型可以表示一組特定的值,并且每個數(shù)據(jù)類型都有一組相關(guān)的操作。從傳統(tǒng)的計算視角出發(fā),我們將數(shù)據(jù)視為一些被動實(shí)體,通過主動操作來控制和組合它們。為了進(jìn)一步地構(gòu)建復(fù)雜系統(tǒng),我們需要采用更豐富的視角來看待數(shù)據(jù)和操作之間的關(guān)系。面向?qū)ο蟪绦蛟O(shè)計(ObjectOrientedProgramming,OOP)是一種計算機(jī)編程架構(gòu),它的一條基本原則是計算機(jī)程序由單個能夠起到子程序作用的單元或?qū)ο蠼M合而成。如今,大多數(shù)現(xiàn)代計算機(jī)程序是用“面向?qū)ο蟆狈椒?gòu)建的,其中的核心概念是類和對象。10.1
面向?qū)ο缶幊痰母拍睢耙詫ο鬄榛A(chǔ)”的程序設(shè)計方式,起源于1960年代末期的Simula語言,經(jīng)過多年發(fā)展研究,例如Smalltalk、C++、Java,逐步發(fā)展出面向?qū)ο蟮娜蠡靖拍睿悍庋b、繼承和多態(tài),都圍繞著控制大型軟件程序的復(fù)雜性、程序代碼重復(fù)使用、穩(wěn)定且易于維護(hù)修改等要求。我們真正想要的是在開發(fā)軟件時,能夠控制程序代碼的復(fù)雜性,編寫出穩(wěn)定的程序,易于維護(hù)和修改,又希望能夠重復(fù)使用。面向?qū)ο蟪绦蛟O(shè)計方法是盡可能模擬人類的思維方式,使得軟件的開發(fā)方法與過程盡可能接近人類認(rèn)識世界、解決現(xiàn)實(shí)問題的方法和過程,也即使得描述問題的問題空間與問題的解決方案空間在結(jié)構(gòu)上盡可能一致,把客觀世界中的實(shí)體抽象為問題域中的對象。10.2類與對象對象的定義類的定義對象的建立10.2
類與對象面向過程程序設(shè)計把程序視為一組過程(模塊、函數(shù))的集合,每個過程都可以接收并處理其他過程發(fā)出的消息,程序的執(zhí)行就是一系列消息在各個過程之間的加工和傳遞。面向?qū)ο蟪绦蛟O(shè)計則是以對象為核心,把對象作為程序的基本單元,對象包含了數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)。為了簡化程序設(shè)計,面向?qū)ο筮^程把函數(shù)繼續(xù)切分為子函數(shù)來降低系統(tǒng)的復(fù)雜度。換句話說,是將“對象”定義為一種主動的數(shù)據(jù)類型,它知道一些事情并可以做一些事情。10.2.1對象的定義一個對象包括:(1)一組相關(guān)的信息。(2)操作這些信息的一組操作(又稱為“方法”)。信息存儲在對象的“實(shí)例變量”中,操作是“存在”于對象中的函數(shù),實(shí)例變量和操作一起被稱為對象的“屬性”。事實(shí)上,Python中的所有數(shù)據(jù)類型都可以視為對象,當(dāng)然也可以自定義對象。自定義的對象數(shù)據(jù)類型就是面向?qū)ο笾械念悾╟lass)的概念。10.2.1對象的定義我們以一個處理學(xué)生成績表的例子來說明面向?qū)ο蟮某绦蛄鞒?。面向?qū)ο蟪绦蛟O(shè)計首先考慮Student這種數(shù)據(jù)類型應(yīng)該被視為一個對象,這個對象擁有name和score這兩個屬性。如果要打印一個學(xué)生的成績,首先必須創(chuàng)建出這個學(xué)生對應(yīng)的對象的實(shí)例,然后給該對象實(shí)例發(fā)一個print_score消息,讓對象實(shí)例自己把數(shù)據(jù)打印出來。classStudent(object):def__init__(self,name,score):=nameself.score=scoredefprint_score(self):print('%s:%s'%(,self.score))10.2.1對象的定義給對象發(fā)消息實(shí)際上就是調(diào)用對象對應(yīng)的關(guān)聯(lián)函數(shù)(方法)。面向?qū)ο蟪绦蛞匀缦滦问綄?shí)現(xiàn):ming=Student('xiaoming',59)fang=Student('xiaofang',87)ming.print_score()fang.print_score()10.2.2類的定義類是對現(xiàn)實(shí)世界的抽象,包括表示靜態(tài)屬性的數(shù)據(jù)和對數(shù)據(jù)的操作,對象是類的實(shí)例化。對象間通過消息傳遞相互通信,來模擬現(xiàn)實(shí)世界中不同實(shí)體間的聯(lián)系。以Python的class語句來自行定義類,其語法如下:class類名(父類,...):
語句下面則是最簡單的類定義classMyClass():pass首先以關(guān)鍵字class開頭,之后是由你取的新類名稱,后面括號內(nèi)可放進(jìn)此類欲繼承的父類,然后是冒號“:”,之后跟著眾多程序語句,此例除了pass語句,其他什么都沒有。10.2.2類的定義我們知道在Python里所有東西都是對象,整數(shù)、浮點(diǎn)數(shù)、列表是對象,甚至模塊、函數(shù)、類也是對象,所以上面的類定義,將會產(chǎn)生出類對象。既然是對象,也就具有命名空間的功能,可放入名稱指向各種其他對象,稱為屬性項(xiàng)。>>>classMyClass(): #類定義...pass...>>>MyClass #名稱MyClass指向類型為class的對象<class'__main__.MyClass'>>>>MyClass.pi=3.14 #具有命名空間的功能>>>MyClass.pi #屬性項(xiàng)pi指向整數(shù)對象3.143.14>>>deffoo():print('hello')10.2.2類的定義...>>>MyClass.bar=foo #MyClass屬性項(xiàng)bar指向函數(shù)對象>>>MyClass.bar<functionfooat0x00C73228>10.2.2類的定義10.2.2類的定義不過,我們通常會以class語句定義新的類,定義時便決定好里頭含有的數(shù)據(jù)成員與方法界面,然后以之作為樣板建立許多對象。例如讓我們定義銀行賬戶類:classBankAccount(): #定義類
def__init__(self): #初始化
self.balance=0 #建立名稱balance,代表余額
defdeposit(self,amount): #存款
self.balance+=amountdefwithdraw(self,amount):#提款
self.balance-=amountdefget_balance(self):#顯示余額
returnself.balance10.2.2類的定義ac0=BankAccount() #構(gòu)造函數(shù),建立銀行賬戶對象print(ac0.balance) #直接存取余額ac0.deposit(100) #存款100ac0.withdraw(30) #提款30print(ac0.get_balance()) #透過方法得到余額ac1=BankAccount() #建立另一個銀行賬戶對象ac1.deposit(1000)print(ac1.get_balance())10.2.2類的定義10.2.2類的定義建立實(shí)例后,便可通過類定義中的方法來存取,例如deposit代表存款、withdraw代表提款。嚴(yán)格說來,deposit與withdraw只是函數(shù)而已,但使用“實(shí)例.方法(參數(shù))”的語法時,Python解釋器會轉(zhuǎn)成“函數(shù)(實(shí)例,參數(shù))”的形式,為此,我們在定義方法時,第一個參數(shù)self是特別的,代表實(shí)例對象本身,而在執(zhí)行方法時,便是通過self來存取該實(shí)例對象里的屬性項(xiàng),也就是各種數(shù)據(jù)(例如賬戶余額)與其他方法。對象的屬性通過點(diǎn)符號訪問。Python中,類中方法定義的第一個參數(shù)始終是self,表示引用方法的對象自身。>>>classMyClass(): #類定義...def__init__(self): #__init__函數(shù)是內(nèi)置方法...self.x=3...deffoo(self):...self.x+=1...print(self.x)...defbar(abc):...abc.x-=1...print(abc.x)10.2.2類的定義...>>>c=MyClass() #建立實(shí)例>>>c.foo() #調(diào)用方法4>>>MyClass.foo(c) #調(diào)用函數(shù)5>>>c.bar(c) #調(diào)用函數(shù)410.2.2類的定義10.2.2類的定義在上面例子中,若是“c.foo()”的語法,我們會把foo當(dāng)作方法,若是“MyClass.foo(c)”的語法,則把foo當(dāng)作函數(shù),其實(shí)沒什么不同,方法就是作為類屬性項(xiàng)的函數(shù),而“實(shí)體.方法(參數(shù))”的語法更為直觀方便。10.2.3對象的建立面向?qū)ο蟮脑O(shè)計思想是抽象出類,根據(jù)類創(chuàng)建實(shí)例。面向?qū)ο蟮某橄蟪潭缺群瘮?shù)要高,因?yàn)轭惣劝瑪?shù)據(jù),又包含操作數(shù)據(jù)的方法。面向?qū)ο笞钪匾母拍罹褪穷惡蛯?shí)例,必須牢記類是抽象的模板,實(shí)例是根據(jù)類創(chuàng)建出來的一個個具體的“對象”
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《WK公司應(yīng)收賬款管理案例研究》
- 表內(nèi)乘除法口算練習(xí)題
- 2024年度大蒜現(xiàn)貨交易市場推廣與合作營銷合同3篇
- 文學(xué)理論教學(xué)實(shí)踐-洞察分析
- 2024年版住宅買賣授權(quán)委托協(xié)議
- 游戲資產(chǎn)數(shù)字化趨勢-洞察分析
- 2024內(nèi)貿(mào)集裝箱貨物運(yùn)輸代理與保險一體化服務(wù)合同
- 血液制品質(zhì)量控制體系完善-洞察分析
- 2024年度魚池轉(zhuǎn)讓及養(yǎng)殖產(chǎn)業(yè)一體化服務(wù)合同范本3篇
- 模板04 說明文-備戰(zhàn)2022年中考英語書面表達(dá)滿分作文萬能模板
- 【《“雙減”背景下小學(xué)數(shù)學(xué)創(chuàng)新作業(yè)設(shè)計問題研究》(論文)】
- 廉政知識競賽大題庫及答案(共500道)
- 德勤-2023年印度尼西亞投資之窗 (IWI) 中文版
- 電力建設(shè)工程現(xiàn)行主要質(zhì)量標(biāo)準(zhǔn)、規(guī)范清單
- 2023年高校輔導(dǎo)員基礎(chǔ)知識復(fù)習(xí)題(附答案)
- 專題02:名著導(dǎo)讀-2022-2023學(xué)年八年級語文下學(xué)期期中專題復(fù)習(xí)(北京專用)
- 吉林大學(xué)藥學(xué)導(dǎo)論期末考試高分題庫全集含答案
- 2023-2024學(xué)年河北省唐山市灤州市數(shù)學(xué)七年級第一學(xué)期期末教學(xué)質(zhì)量檢測模擬試題含解析
- 高考語文新題型+“文學(xué)短評”相關(guān)寫作(真題+技法+練習(xí))
- 中考數(shù)學(xué)計算題100道
- 集團(tuán)資產(chǎn)重組實(shí)施方案
評論
0/150
提交評論