6. 輸入輸出
6.1 設(shè)計(jì)輸出格式
輸出值的方法:表達(dá)式語(yǔ)句、print語(yǔ)句和write()方法。
想要對(duì)輸入字符串格式做一些復(fù)雜的控制,有兩種方法。第一,控制整個(gè)字符串,使用字符切割和聯(lián)接操作創(chuàng)建任意輸出形式。第二,使用%操作符和字符串作為左參數(shù)。%操作符將左參數(shù)解釋為類似于sprintf()風(fēng)格的格式字符串,并作用于右參數(shù),從操作中返回格式化的字符串。
Python中可以使用repr()或str()函數(shù),將值轉(zhuǎn)為字符串。反引號(hào)('')等價(jià)于repr()。這些函數(shù)在未來(lái)的Python版本中將會(huì)被去掉。
函數(shù)str()用于將值轉(zhuǎn)化為適于人閱讀的形式,而repr()轉(zhuǎn)化為共解釋器讀取的形式(如果沒(méi)有等價(jià)的語(yǔ)法,則會(huì)發(fā)生SyntaxError異常)。某對(duì)象沒(méi)有適于人閱讀的解釋形式時(shí),str()會(huì)返回與repr()等同的值。數(shù)值、鏈表、字典對(duì)各函數(shù)有統(tǒng)一的解讀方式。字符串和浮點(diǎn)數(shù),有獨(dú)特的解讀方式。
示例:
>>> s= 'Hello World!'
>>> str(s)
'Hello World!'
>>> repr(s)
"'Hello World!'"
>>> str(0.1)
'0.1'
>>> repr(0.1)
'0.10000000000000001'
>>> hello = 'hello world\n'
>>> print hello
hello world
>>> print repr(hello)
'hello world\n'
>>> print str(hello)
hello world
>>> x = 10*3.25
>>> y = 200*200
>>> 'x, y, (`spam`,`eggs`)'
'x, y, (`spam`,`eggs`)'
>>>
一個(gè)輸出平方和立方的例子:
>>> for x in range(1, 11):
... print repr(x).rjust(2), repr(x*x).rjust(3),
... print repr(x*x*x).rjust(4)
...
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
>>>
print方法總會(huì)在兩個(gè)參數(shù)之間增加一個(gè)空格。rjust()函數(shù)參數(shù)為輸出所占的位數(shù),輸出方式為右對(duì)齊。類似的函數(shù)有l(wèi)just()和center()。這些函數(shù)只是輸出新的字符串,并不改變它們,如果輸出的字符串太長(zhǎng),也不會(huì)被截?cái)啵窃瓨虞敵觥H绻財(cái)嘧址梢允褂们懈畈僮鳎纾瑇.ljust(n)[:n]。
zfill()用于向數(shù)值的字符串表達(dá)左側(cè)填充0。該函數(shù)可以正確理解正負(fù)號(hào)。
>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'
>>>
%操作符使用方法
>>> import math
>>> print 'The value of PI is approximately %5.3f.' % math.pi
The value of PI is approximately 3.142.
>>>
如果有超過(guò)一個(gè)的字符串要格式化為一體,就需要將它們傳入一個(gè)元組做為右值:
>>> table = {'A':001, 'B':002, 'C':003}
>>> for name, phone in table.items():
... print '%-10s ==> %10d' % (name, phone)
...
A ==> 1
C ==> 3
B ==> 2
>>>
大多數(shù)類C的格式化操作都需要傳入適當(dāng)?shù)念愋汀J褂?s格式會(huì)更輕松一些:如果對(duì)應(yīng)的參數(shù)不是字符串,它會(huì)通過(guò)內(nèi)置的str()函數(shù)轉(zhuǎn)化為字符串。Python支持用*作為一個(gè)隔離參數(shù)來(lái)傳遞寬度或精度。Python不支持C的%n和%p操作符。
變量格式化通過(guò)名字而不是位置,這樣可以產(chǎn)生符合真實(shí)長(zhǎng)度的格式化字符串,而不用分隔。這一效果可以通過(guò)使用form % (name) format結(jié)構(gòu)來(lái)實(shí)現(xiàn):
>>> table = {'A':001, 'B':002, 'C':003}
>>> print 'A:%(A)d; B:%(B)d; C:%(C)d' % table
A:1; B:2; C:3
>>>
這個(gè)技巧在新的內(nèi)置函數(shù)vars()組合使用時(shí)非常有用,該函數(shù)返回一個(gè)包含所有局部變量的字典。
6.2 讀寫(xiě)文件
open()返回一個(gè)文件,通過(guò)的用法需要兩個(gè)參數(shù):open(filename, mode)
>>> f = open('C:/Users/cym/Desktop/1.txt', 'w')
>>> print f
<open file 'C:/Users/cym/Desktop/1.txt', mode 'w' at 0x03D07548>
>>>
mode有:
r,此選項(xiàng)使文件只讀,默認(rèn)模式;
w,此選項(xiàng)使文件只寫(xiě),對(duì)于已經(jīng)存在的同名文件,該操作覆蓋源文件;
a,此選項(xiàng)以追加方式打開(kāi)文件;
r+,此選項(xiàng)以讀寫(xiě)方式打開(kāi)文件。
在Windows和Moc平臺(tái),b模式以二進(jìn)制方式打開(kāi)文件,所以會(huì)有rb,wb,r+b等等組合。Windows平臺(tái)上文本文件與二進(jìn)制文件是有區(qū)別的,讀寫(xiě)文本文件時(shí),行尾會(huì)自動(dòng)添加行結(jié)束符。這種后臺(tái)操作方式對(duì)ASCII文本文件沒(méi)有什么問(wèn)題,但是操作JPEG或EXE這樣的二進(jìn)制文件就會(huì)產(chǎn)生破壞。在操作這些文件時(shí)一定要記得以二進(jìn)制模式打開(kāi)。
6.2.1 文件對(duì)象方法
讀文件,f.read(size)。該方法讀取若干數(shù)量的數(shù)據(jù)并以字符串形式返回其內(nèi)容,字符串長(zhǎng)度為數(shù)值size所指定的大小。如果沒(méi)有指定size或者指定為負(fù)數(shù),就會(huì)讀取并返回整個(gè)文件。當(dāng)文件大小為當(dāng)前機(jī)器內(nèi)存兩倍時(shí),就會(huì)產(chǎn)生問(wèn)題。正常情況下,會(huì)盡可能按比較大的size讀取和返回?cái)?shù)據(jù)。如果到了文件末尾,f.read()會(huì)返回一個(gè)空字符串。
>>> f = open('C:/Users/cym/Desktop/1.txt', 'r')
>>> f.read()
''
>>>
f.readline()從文件中讀取單獨(dú)一行,字符串結(jié)尾會(huì)自動(dòng)加上一個(gè)換行符,只有當(dāng)文件最后一行沒(méi)有以換行符結(jié)尾時(shí),這一操作才會(huì)被忽略。如果f.readline()返回一個(gè)空字符串,那就表示到達(dá)了文件末尾,如果是一個(gè)空行,就會(huì)描述為\n,一個(gè)只包含換行符的字符串。
f.readlines([size])返回一個(gè)列表,包含了文件中所有的數(shù)據(jù)行。如果給定了size參數(shù),就會(huì)讀入多于一行的比特?cái)?shù),從中返回多行文本。這個(gè)功能通常用于高效讀取大型行文本,避免了將整個(gè)文件讀入內(nèi)存。這種操作只返回完整的行。
一種另外的方法是循環(huán)讀取文件。這是一種內(nèi)存效率高,速度快,代碼簡(jiǎn)單的方法:
>>> for line in f:
... print line,
...
交換通道很簡(jiǎn)單,但是不提供完整的控制。因?yàn)閮蓚€(gè)通道管理線緩沖不同,它們不能混合。
如果需要寫(xiě)入字符串以外的數(shù)據(jù),就要先把這些數(shù)據(jù)轉(zhuǎn)換為字符串。
>>> f = open('C:\\Users\\cym\\Desktop\\test.txt','r+')
>>> value = ('the answer', 42)
>>> s = str(value)
>>> f.write(s)
>>> f.close()
>>>
f.tell()返回一個(gè)整數(shù),代表文件對(duì)象在文件中的指針位置,該數(shù)值計(jì)量了自文件開(kāi)頭到指針處的比特?cái)?shù)。需要改變文件對(duì)象指針的話,使用f.seek(offset, from_what)。指針在該操作中從指定的引用位置移動(dòng)offset比特,引用位置由from_what參數(shù)指定。from_what值為0表示自文件起處開(kāi)始,1表示自當(dāng)前文件指針位置開(kāi)始,2表示自文件末尾開(kāi)始。from_what可以忽略,其默認(rèn)值為0,此時(shí)從文件頭開(kāi)始。
文件使用完后,調(diào)用f.close()可以關(guān)閉文件,釋放打開(kāi)文件后占用的系統(tǒng)資源。調(diào)用f.close()之后,再調(diào)用文件對(duì)象會(huì)自動(dòng)引發(fā)錯(cuò)誤。
文件對(duì)象還有一些不太常用的附加方法,比如isatty()和truncate()。
6.2.2 pickle模塊
我們可以很容易的讀寫(xiě)文件中的字符串。數(shù)值就要多費(fèi)點(diǎn)周折,因?yàn)閞ead()方法只會(huì)返回字符串,應(yīng)該將其傳入int()方法中,就可以將'123'這樣的字符串轉(zhuǎn)為對(duì)應(yīng)的數(shù)值123。不過(guò),當(dāng)你需要保存更為復(fù)雜的數(shù)據(jù)類型,例如鏈表、字典,類的實(shí)例,事情就會(huì)變的更復(fù)雜了。Python提供了一個(gè)名為pickle的標(biāo)準(zhǔn)模塊。這是一個(gè)令人贊嘆的模塊,幾乎可以把任何Python對(duì)象表達(dá)為字符串,這一過(guò)程稱之為封裝。從字符串表達(dá)出重新構(gòu)造對(duì)象之為拆封unpickling。封裝狀態(tài)中的對(duì)象可以存儲(chǔ)在文件或?qū)ο笾校惨酝ㄟ^(guò)網(wǎng)絡(luò)在遠(yuǎn)程的機(jī)器之間傳輸。
如果你有一個(gè)對(duì)象x,一個(gè)以寫(xiě)模式打開(kāi)的文件對(duì)象f,封裝對(duì)象的最簡(jiǎn)單的方法只需要一行代碼:
pickle.dump(x,f)
如果f是一個(gè)以讀模式打開(kāi)的文件對(duì)象,就可以重裝拆封這個(gè)對(duì)象:
x=pickle.load(f)
pickle是存儲(chǔ)Python對(duì)象以供其它程序或其本身以后調(diào)用的標(biāo)準(zhǔn)方法。提供這一組技術(shù)的一個(gè)持久化對(duì)象。因?yàn)閜ickle的用途很廣泛,很多Python擴(kuò)展的作者都非常注意類似矩陣這樣的新數(shù)據(jù)類型是否適合封裝和拆封。