6. 输入输出
6.1 设计输出格式
输出值的方法:表达式语句、print语句和write()方法。
想要对输入字符串格式做一些复杂的控制,有两种方法。第一,控制整个字符串,使用字符切割和联接操作创建任意输出形式。第二,使用%操作符和字符串作为左参数。%操作符将左参数解释为类似于sprintf()风格的格式字符串,并作用于右参数,从操作中返回格式化的字符串。
Python中可以使用repr()或str()函数,将值转为字符串。反引号('')等价于repr()。这些函数在未来的Python版本中将会被去掉。
函数str()用于将值转化为适于人阅读的形式,而repr()转化为共解释器读取的形式(如果没有等价的语法,则会发生SyntaxError异常)。某对象没有适于人阅读的解释形式时,str()会返回与repr()等同的值。数值、链表、字典对各函数有统一的解读方式。字符串和浮点数,有独特的解读方式。
示例:
>>> 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`)'
>>>
一个输出平方和立方的例子:
>>> 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方法总会在两个参数之间增加一个空格。rjust()函数参数为输出所占的位数,输出方式为右对齐。类似的函数有ljust()和center()。这些函数只是输出新的字符串,并不改变它们,如果输出的字符串太长,也不会被截断,而是原样输出。如果要截断字符串,可以使用切割操作,如,x.ljust(n)[:n]。
zfill()用于向数值的字符串表达左侧填充0。该函数可以正确理解正负号。
>>> '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.
>>>
如果有超过一个的字符串要格式化为一体,就需要将它们传入一个元组做为右值:
>>> table = {'A':001, 'B':002, 'C':003}
>>> for name, phone in table.items():
... print '%-10s ==> %10d' % (name, phone)
...
A ==> 1
C ==> 3
B ==> 2
>>>
大多数类C的格式化操作都需要传入适当的类型。使用%s格式会更轻松一些:如果对应的参数不是字符串,它会通过内置的str()函数转化为字符串。Python支持用*作为一个隔离参数来传递宽度或精度。Python不支持C的%n和%p操作符。
变量格式化通过名字而不是位置,这样可以产生符合真实长度的格式化字符串,而不用分隔。这一效果可以通过使用form % (name) format结构来实现:
>>> table = {'A':001, 'B':002, 'C':003}
>>> print 'A:%(A)d; B:%(B)d; C:%(C)d' % table
A:1; B:2; C:3
>>>
这个技巧在新的内置函数vars()组合使用时非常有用,该函数返回一个包含所有局部变量的字典。
6.2 读写文件
open()返回一个文件,通过的用法需要两个参数: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,此选项使文件只读,默认模式;
w,此选项使文件只写,对于已经存在的同名文件,该操作覆盖源文件;
a,此选项以追加方式打开文件;
r+,此选项以读写方式打开文件。
在Windows和Moc平台,b模式以二进制方式打开文件,所以会有rb,wb,r+b等等组合。Windows平台上文本文件与二进制文件是有区别的,读写文本文件时,行尾会自动添加行结束符。这种后台操作方式对ASCII文本文件没有什么问题,但是操作JPEG或EXE这样的二进制文件就会产生破坏。在操作这些文件时一定要记得以二进制模式打开。
6.2.1 文件对象方法
读文件,f.read(size)。该方法读取若干数量的数据并以字符串形式返回其内容,字符串长度为数值size所指定的大小。如果没有指定size或者指定为负数,就会读取并返回整个文件。当文件大小为当前机器内存两倍时,就会产生问题。正常情况下,会尽可能按比较大的size读取和返回数据。如果到了文件末尾,f.read()会返回一个空字符串。
>>> f = open('C:/Users/cym/Desktop/1.txt', 'r')
>>> f.read()
''
>>>
f.readline()从文件中读取单独一行,字符串结尾会自动加上一个换行符,只有当文件最后一行没有以换行符结尾时,这一操作才会被忽略。如果f.readline()返回一个空字符串,那就表示到达了文件末尾,如果是一个空行,就会描述为\n,一个只包含换行符的字符串。
f.readlines([size])返回一个列表,包含了文件中所有的数据行。如果给定了size参数,就会读入多于一行的比特数,从中返回多行文本。这个功能通常用于高效读取大型行文本,避免了将整个文件读入内存。这种操作只返回完整的行。
一种另外的方法是循环读取文件。这是一种内存效率高,速度快,代码简单的方法:
>>> for line in f:
... print line,
...
交换通道很简单,但是不提供完整的控制。因为两个通道管理线缓冲不同,它们不能混合。
如果需要写入字符串以外的数据,就要先把这些数据转换为字符串。
>>> f = open('C:\\Users\\cym\\Desktop\\test.txt','r+')
>>> value = ('the answer', 42)
>>> s = str(value)
>>> f.write(s)
>>> f.close()
>>>
f.tell()返回一个整数,代表文件对象在文件中的指针位置,该数值计量了自文件开头到指针处的比特数。需要改变文件对象指针的话,使用f.seek(offset, from_what)。指针在该操作中从指定的引用位置移动offset比特,引用位置由from_what参数指定。from_what值为0表示自文件起处开始,1表示自当前文件指针位置开始,2表示自文件末尾开始。from_what可以忽略,其默认值为0,此时从文件头开始。
文件使用完后,调用f.close()可以关闭文件,释放打开文件后占用的系统资源。调用f.close()之后,再调用文件对象会自动引发错误。
文件对象还有一些不太常用的附加方法,比如isatty()和truncate()。
6.2.2 pickle模块
我们可以很容易的读写文件中的字符串。数值就要多费点周折,因为read()方法只会返回字符串,应该将其传入int()方法中,就可以将'123'这样的字符串转为对应的数值123。不过,当你需要保存更为复杂的数据类型,例如链表、字典,类的实例,事情就会变的更复杂了。Python提供了一个名为pickle的标准模块。这是一个令人赞叹的模块,几乎可以把任何Python对象表达为字符串,这一过程称之为封装。从字符串表达出重新构造对象之为拆封unpickling。封装状态中的对象可以存储在文件或对象中,也以通过网络在远程的机器之间传输。
如果你有一个对象x,一个以写模式打开的文件对象f,封装对象的最简单的方法只需要一行代码:
pickle.dump(x,f)
如果f是一个以读模式打开的文件对象,就可以重装拆封这个对象:
x=pickle.load(f)
pickle是存储Python对象以供其它程序或其本身以后调用的标准方法。提供这一组技术的一个持久化对象。因为pickle的用途很广泛,很多Python扩展的作者都非常注意类似矩阵这样的新数据类型是否适合封装和拆封。