文件——在文件中存储Python对象:转换
下一个例子将许多 Python 对象以多行形式写入文本文件。注意必须使用转换工具把对象转换为字符串。再说一次,在脚本中文件数据总是字符串,write
方法不为我们做任何自动的 to-string
格式化(为节省空间,从这里开始我会省略到从 write
方法返回的字节数):
>>> X, Y, Z = 43, 44, 45 # Native Python objects
>>> S = 'Spam' # Must be strings to store in file
>>> D = {'a': 1, 'b': 2}
>>> L = [1, 2, 3]
>>>
>>> F = open('datafile.txt', 'w') # Create output text file
>>> F.write(S + '\n') # Terminate lines with \n
>>> F.write('%s,%s,%s\n' % (X, Y, Z)) # Convert numbers to strings
>>> F.write(str(L) + '$' + str(D) + '\n') # Convert and separate with $
>>> F.close()
一旦创建了文件,就可以通过将其打开并读取到字符串中来查看其内容(这里将其串起来作为一个操作)。注意交互式回显给出了精确的字节内容,然而 print
操作解释了嵌入的行尾字符来渲染出一个更用户友好的显示:
>>> chars = open('datafile.txt').read() # Raw string display
>>> chars
"Spam\n43,44,45\n[1, 2, 3]${'a': 1, 'b': 2}\n"
>>> print(chars) # User-friendly display
Spam
43,44,45
[1, 2, 3]${'a': 1, 'b': 2}
现在必须使用其他的转换工具来把文本文件中的字符串转换为真正的 Python 对象。因为 Python 从不自动转换字符串为数字(或其它对象类型),如果需要获得普通对象工具如索引、加法等的权限,那么(手动)转换就是必须的:
>>> F = open('datafile.txt') # Open again
>>> line = F.readline() # Read one line
>>> line
'Spam\n'
>>> line.rstrip() # Remove end-of-line
'Spam'
对第一行,使用了字符串 rstrip
方法来去除尾随的行尾字符;line[:-1]
的切片也可以,但只有当我们确定所有行都以 \n
结尾(文件的最后一行有时并不是这样)才行。
到目前为止,已经读取了包含字符串的行。现在让我们获取下一行(它包含了数字),然后解析出(也就是:提取)那行上的对象:
>>> line = F.readline() # Next line from file
>>> line # It's a string here
'43,44,45\n'
>>> parts = line.split(',') # Split (parse) on commas
>>> parts
['43', '44', '45\n']
这里使用了字符串 split
方法按该行的逗号分隔符将其分成几份;结果是包含单个数字的子字符串列表。然而,如果希望在这些字符串上进行运算,仍然必须将字符串转为数字:
>>> int(parts[1]) # Convert from string to int
44
>>> numbers = [int(P) for P in parts] # Convert all in list at once
>>> numbers
[43, 44, 45]
已经学过:int
将数字符号的字符串转换为整数对象,在第 4 章介绍的列表 comprehension 表达式可以一次性对列表中的每一项进行调用(本书后面会找到关于列表 comprehension 的更多知识)。注意没必要运行 rstrip
来删除最后一部分末尾的 \n
;int
和其它转换器会默默地忽略掉数字旁边的 whitespace
。
最后,要转换文件第三行中的列表和字典,可以对它们运行 eval
(一个将字符串作为可执行程序代码片段 —— 技术上指的是包含 Python 表达式中的字符串 —— 的内置函数):
>>> line = F.readline()
>>> line
"[1, 2, 3]${'a': 1, 'b': 2}\n"
>>> parts = line.split('$') # Split (parse) on $
>>> parts
['[1, 2, 3]', "{'a': 1, 'b': 2}\n"]
>>> eval(parts[0]) # Convert to any object type
[1, 2, 3]
>>> objects = [eval(P) for P in parts] # Do same for all in list
>>> objects
[[1, 2, 3], {'a': 1, 'b': 2}]
因为所有这些解释和转换的最终结果是普通对象的列表而非字符串,所以现在可以在脚本中对它们应用列表和字典的操作。
推荐文章: