一个程序的输出有多重方式;数据可以展示成人类易读的方式或是写入一个文件等待以后使用,这一章我们就会讨论这些方式。
7.1 Fancier Output Formatting
到目前位置我们已经遇到了两种输出变量的方法:表达式协议和print()函数。很多时候你想要更精细的控制你的输出结果而不是简单的让他们又空格分隔开来,有两种方法去制定你的输出格式;第一种方法是自己处理所有的字符串,使用分片操作和串联可以把所有你想的方式都创造出来。字符串本身有一些能够制定列宽并排版的方法我们稍后会说到。第二种方法是使用制定好的格式或者使用str.format()方法。string模块中的template类中还提供了另外的替换字符的方法。
还有一个问题:我们怎么把变量转换成字符串?幸运的是python有repr()和str()函数可以将任何变量转换成字符串。str()函数的返回值更加适合人类阅读,而repr()函数的返回值则更适合解释器去理解。对于一些本身就不适合人阅读的类,str()和repr()的返回值是一样的。许多变量比如列表、数字、字典之类的用两者的结果都是一样的。字符串实际上是有两种表现形式的。举个例子:
另外如果使用repr()函数转换的字符串中包含/(反斜线)的话,就会对他们都使用转义字符(也是反斜线):
在看一个将复杂元组转换成字符串的栗子:
下面我们展示两种制作平方立方表的方法:
这里的str.rjust()是字符右对其的方法,我们还可以直接使用参数设置格式:
{0:2d}前面的0表示第1个元素,:2d表示占两个宽度。第一个例子中print自动为每个元素之间增加空格,第二个例子中是我们自己加的,print函数会为逗号间隔的元素之间增加空格。另外我们在详细的介绍下str.rjust(),他会让字符靠右左边用空格填充,ljust()就是靠左,center()就是居中。这些方法并不会修改原来的字符串,而是直接返回一个新的字符串。如果输入的字符串太长了,比我们设置的宽度还要长那么就会返回原值而不会切割字符串。如果实在是想要切了它的话可以是用str.rjust()[:n]。
还有一个叫做str.zfill()的方法,他设定了宽度之后让字符串的左面填满0。符号也是计入这个宽度内的:
一般str.format()的用法遵循下面的格式:
花括号和其内的内容会被传入到format方法里的参数所取代,可以在花括号内使用数字来表示用第几个元素来替代这个花括号:
也可以用关键字来作为序号:
花括号内还有三种选项能调用ascii()、str()、repr()分别是!a、!s、!r:
还有许多str.format()的内容我们并不一一介绍了,可以看formatstrings这个部分。
7.1.1 Old string formating
%符号也是可以用来制定输出的格式的,左面的%会被右面的元素安装制定的方法替代,看个例子挺好明白的:
更多的信息可以看old-string-formating。
7.2 Reading and Writing Files
open函数常用filename和mode两个参数:open('filename', 'mode')他会返回一个file对象。
第一个参数传递的是文件名,第二个参数是用来选择打开方式的。有多重方式可选,默认情况就是没有参数的情况会将参数默认为’r‘,就是只读模式。'w'为只允许写入、'a'为追加模式、'b'为二进制模式、'r+'表示能同时读写。一般情况来说文件都是作为文本来打开的,我们可以向其中书写字符串或是阅读里面已有的内容,字符串的编码类型一般都是所在的平台默认的,当然也是可以指定的。使用'b'模式打开文件,其中的内容都是二进制表示的,这适用于不含文本的文件。在阅读模式,无论在什么平台python都会把行终止符转换为\n,而在写入的时候会把\n转换为各个平台的特定终止符。这个机制对于文本来说可能没啥事,但是对于二进制文件这可能是致命的。所以在操作二进制文件的时候一定要小心。
7.2.1 Methods of File Objects
下面的例子里我们假设已经生成了一个叫做f的文件对象,只是让大家了解一下用法。我们使用read(size)方法来读取文件的内容,size表示读取出来的字符串或字节的数量。如果省略了size或者设置为负数就会把所有的文本读出来。如果已经读到了文本的末尾,再次使用read()方法就会返回空的字符串:
可以使用realine()来逐行返回字符串,在字符串的末尾会保留一个\n。只有在最后一行会省略这个\n,这种机制的设计可以保证我们获取时不会出错:
·
可以使用for循环来逐行的返回字符串,在下面这个例子里字符会空一行是因为print函数也会添加\n:
如果想要把文件内的文本转换为列表可以使用list(file)或者f.readlines(),向文件内增加文本使用f.write(string),同时会返回增加的字符数量(使用转义字符算作一个字符):
其他的类型在写入文件之前需要先进行类型转换:
使用tell()方法可以返回我们已经读了多少,想改变当前位置使用f.seek(offset, from_what)。offset表示距离目标的位置,from_what有三个参数0、1、2。其中0表示文件开头,1表示当前位置,2表示文件的末尾。看几个例子很容易理解:
注意上面的这些方法只有在b模式下可用,在文本模式下只能从文件开头开始找位置,from_what就没有1、2这两个选项了。当一个文件完成了他的使命后,就可以把他关闭了以节省计算机的宝贵空间,这个时候在调用它就会报错:
还有一个with结构,可以自动的关闭用完的文件,他的用法和try比较像,我们看个例子:
文件对象还有许多其他的方法,比如isatty()和truncate(),但这里我们就不都一一讲述了,感兴趣可以去看标准库里的相关内容。
7.2.2 Saving structured data with json
字符串可以很轻松的输入输出,与之相比数字会麻烦一些,因为文件的输入输出都是转换为字符串的。当你想要存储一些复杂的内容,比如嵌套的列表和字典,那么手动的去解析和序列化都是很麻烦的事。为此,python允许用户使用json(JavaScript Object Notation),这是一个数据转换的协议。json标准库继承了python的数据类型,他可以将数据转换成字符串,这个过程叫做序列化;而重新使字符串变成其他的数据类型就叫做反序列化。这个转换可以让我们方便的储存和传输这些非字符串的变量。
下面我们看看json会把我们的对象变成什么样:
使用dump可以直接将序列化的对象写入文件中:
json.dump(x, f)
可以使用load来解析一个文件中的对象:
x = json.load(f)
像是序列和字典可以很方便的转化,但是一些其他的对象实例就需要一些其他的工作了。这些可以在json模块的参考中看到。