Python3.7官方向导翻译之Python输入和输出

这里有几种方法来呈现程序的输出;数据可以以人类可读的形式打印,或者写入文件以供将来使用。本章将讨论一些可能性。

理想的输出格式(fancier)

到目前为止,我们遇到了两种写入值的方法:表达式语句和print()函数。 (第三种方法是使用文件对象的write()方法;标准输出文件可以被引用为sys.stdout。有关这方面的更多信息,请参阅Library Reference。)

通常,您需要更多地控制输出的格式,而不仅仅是打印空格分隔的值。 有两种方法可以格式化输出; 第一种方法是自己完成所有的字符串处理; 使用字符串切片和连接操作,您可以创建任何您能想到的布局。 字符串类型有一些方法可以将字符串填充到给定的列宽度; 这些将在短期内讨论。 第二种方法是使用格式化的字符串文字或str.format()方法。

string模块包含一个Template类,它提供了另一种将值替换为字符串的方法。

当然,还有一个问题:如何将值转换为字符串? 幸运的是,Python有办法将任何值转换为字符串:将它传递给repr()或str()函数。

str()函数用于返回值相当人类可读的表示,而repr()则用于生成可由解释器读取的表示(或者,如果没有等效语法,将强制执行SyntaxError)。 对于没有用于人类消费的特定表示的对象,str()将返回与repr()相同的值。 许多值,如数字或结构(列表和词典等))使用任一函数具有相同的表示形式。 特别是字符串有两个不同的表示。

s = 'hello, world.'
str(s)
'hello, world.'
repr(s)
"'hello, world.'"
str(1/7)
'0.14285714285714285'
x = 10 * 3.25
y = 200 * 200
s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
print(s)
The value of x is 32.5, and y is 40000...
# The repr() of a string adds string quotes and backslashes:字符串的repr()添加字符串引号和反斜杠:
hello = 'hello world.\n'
hellos = repr(hello)
print(hellos)
'hello world.\n'
# The argument to repr() may be any Python object:
repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"

这里有两种方法来编写正方形和立方体的表格:

for x in range(1, 11):
    print(repr(x).rjust(2), repr(x*x).rjust(3), end= ' ')
    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
for x in range(1, 11):
    print(' {0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
  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()的工作方式添加:默认情况下它会在其参数之间添加空格。)

这个例子演示了字符串对象的str.rjust()方法,它在给定宽度的字段中通过填充左边的空格来右对齐字符串。 有类似的方法str.ljust()和str.center()。 这些方法不写任何东西,它们只是返回一个新的字符串。 如果输入的字符串太长,它们不会截断它,但会以原样返回; 这会弄乱你的专栏布局,但通常比替代方案更好。 (如果你真的需要截断,你总是可以添加一个slice操作,就像在x.ljust(n)[:n]中一样)。

还有另一种方法str.zfill(),它用左边的数字字符串填充零。 它理解加号和减号(正负):

'12'.zfill(5)
'00012'
'-3.14'.zfill(7)
'-003.14'
'3.14159265359'.zfill(5)
'3.14159265359'

str.format()方法的基本用法如下所示:

print('We are the {} who say "{}!"'.format('knights', 'N1'))
We are the knights who say "N1111!"

它们中的括号和字符(称为格式字段format field)被传递给str.format()方法的对象替换。 括号中的数字可以用来指向传入str.format()方法的对象的位置。

print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam

如果在str.format()方法中使用关键字参数,则使用参数的名称引用它们的值。

print('This {food} is {adjective}'.format(food = 'spam', adjective = 'absolutely orrible'))
This spam is absolutely orrible

位置参数和关键字参数可以随意组合

print('The story of {0}, {1}, and {other}'.format('Bill', 'Manfred', other = 'Georg'))
The story of Bill, Manfred, and Georg

‘!a’(用于ascii()), ‘!s’(用于str()) 和’!r’(用于repr())可以用于在它被格式化之前转换值。

contents = 'eels'
print('My hovercraft is full of {}.'.format(contents))
My hovercraft is full of eels.
print('My hovercraft is full of {!r}.'.format(contents))
My hovercraft is full of 'eels'.

可选的’:’和格式说明符可以跟在字段名称后面。 这可以更好地控制值的格式。 下面的例子将Pi循环到小数点后的三个位置。

import math
print('The value of PI is approximately {0:.3f}.'.format(math.pi))
The value of PI is approximately 3.142.

在’:’之后传递一个整数将导致该字段有最小字符宽度。 这对制作漂亮的表格非常有用

table = {'Sjoerd':4127, 'Jack':4098, 'Dcab':7678}
for name, phone in table.items():
    print('{0:10} ==> {1:10d}'.format(name, phone))
Sjoerd     ==>       4127
Dcab       ==>       7678
Jack       ==>       4098

如果你有一个非常长的格式字符串,但你不想分割,如果你可以引用变量来按名称而不是按位置格式化,那将是很好的。 这可以通过简单地传递字典并使用方括号’[]’来访问键来完成

table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
'Dcab: {0[Dcab]:d}'.format(table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

这也可以通过将表格作为关键字参数传递给’**’符号来完成。

table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

这与内置函数vars()结合使用会特别有用,它会返回一个包含所有局部变量的字典。

有关使用str.format()进行字符串格式化的完整概述,请参阅格式字符串语法format string syntax。

旧的字符串格式

%运算符也可以用于字符串格式。 它将左边的参数解释成很像sprintf()样式的格式字符串以应用于正确的参数,并返回由此格式化操作产生的字符串。 例如

import math
print('The value of PI is approximatley %5.3f.' % math.pi)
The value of PI is approximatley 3.142.

更多信息可以在printf-style的字符串格式部分找到。

读和写文件

open()返回一个文件对象,最常用于两个参数:open(filename,mode)。

f = open('workfile', 'w')

第一个参数是一个包含文件名的字符串。 第二个参数是另一个包含几个字符的字符串,用于描述文件的使用方式。 模式可以是’r’,只有文件将被读取,’w’只能写入(同名的现有文件将被删除),’a’打开要附加的文件; 写入文件的任何数据都会自动添加到结尾。 ‘r +’打开文件以读取和写入。 模式参数是可选的; 如果忽略的话,默认为’r’。

通常情况下,文件以文本模式打开,这意味着您可以读取和写入文件中的字符串,并以特定的编码进行编码。 如果未指定编码,则默认值取决于平台(请参阅open())。 ‘b’附加到模式下以二进制模式打开文件:现在数据以字节对象的形式读取和写入。 该模式应该用于所有不包含文本的文件

在文本模式下,读取时的默认设置是将平台特定的行结束符(Unix上的\ n,Windows上的\ r \ n)转换为\ n。 在文本写模式下,默认情况下将\ n的转换为平台指定的行结束符。 这种对文件数据的后台修改对于文本文件来说很好,但会破坏JPEG或EXE文件中的二进制数据。 在读写这些文件时要非常小心地使用二进制模式。

处理文件对象时,最好使用with关键字。 优点是,即使在某个时间点出现异常,文件在其套件结束后也能正常关闭。 使用with也比编写等价的try-finally块短得多:

with open('workfile') as f:
    read_data = f.read()

#此时输入f.closed。结果会是True

如果你不使用with关键字,那么你应该调用f.close()来关闭文件,并立即释放它使用的任何系统资源。 如果你没有明确地关闭一个文件,Python的垃圾回收器最终会破坏这个对象并为你关闭这个打开的文件,但是这个文件可能会保持打开一段时间。 另一个风险是不同的Python实现会在不同的时间进行这种清理。

通过使用with语句或者调用f.close()函数使得文件对象关闭后,如果在试图使用文件对象就会失败。

f.close()
#if use f.read, it will come with "ValueError: I/O operation on closed file"

文件对象方法

本节中的其余例子将假设已经创建了一个名为f的文件对象。

要读取文件内容,请调用读取一定数量数据的f.read(size),并以字符串(文本模式)或字节对象(二进制模式)的形式返回。 size是可选的数字参数。 当size被忽略或是负数时,文件的全部内容将被读取并返回; 如果文件是机器内存的两倍,那就是你的问题。 否则,读取并返回最多大小的字节。 如果文件已达到末尾,f.read()将返回一个空字符串(”)。

f.read()

f.readline()从文件读取一行; 一个换行符(\ n)留在字符串的末尾,并且如果该文件不以换行符结束,则仅在文件的最后一行中省略换行符(\ n)。 这使得返回值明确; 如果f.readline()返回一个空字符串,文件的末尾已经到达,而空行用’\ n’表示,这是一个只包含一个换行符的字符串。

cat1.jpg

你可以循环读取文件行,这种方式节省内存,快速并且代码简单

这里写图片描述

如果你想将所有行读到一个列表中,你可以使用list(f)或者f.readlines()。

f.write(string) 写字符串到文件中,返回写入的字符数量。

这里写图片描述

有一种对象在写之前需要将他们转化为字符串(文本格式)或者字节对象(二进制格式)。

这里写图片描述

f.tell()返回一个整数,它给出文件中文件对象的当前位置,表示为二进制模式下文件开头的字节数,以及文本模式下的不透明数

要更改文件对象的位置,请使用f.seek(offset,from_what)。 该位置是通过将偏移量添加到参考点来计算的; 参考点由from_what参数选择。from_what值为0表示文件开始,1使用当前文件位置,2使用文件结尾作为参考点。 from_what可以省略,默认为0,使用文件的开头作为参考点。

这里写图片描述

在文本文件中(那些在模式字符串中没有ab的情况下打开的文件),只允许相对于文件的开头寻找(例外情况是以seek(0,2)寻找文件尾),唯一有效的偏移值是 那些从f.tell()返回的,或者是零。 任何其他偏移值都会产生未定义的行为。

用json保存结构化数据

字符串可以很容易地写入和读取文件。 由于read()方法只返回字符串,因此数字需要更多的努力,因为read()方法必须传递给像int()这样的函数,该函数接受一个像’123’这样的字符串并返回它的数字值123.当你想要 保存更复杂的数据类型,如嵌套列表和字典,手动解析和序列化变得复杂。

Python不是让用户不断地编写和调试代码来将复杂的数据类型保存到文件中,而是允许您使用流行的数据交换格式JSON(JavaScript Object Notation)。 称为json的标准模块可以采用Python数据层次结构,并将其转换为字符串表示形式; 这个过程被称为序列化serializing。 重建字符串表示中的数据称为反序列化deserializing。 在序列化和反序列化之间,表示对象的字符串可能已被存储在文件或数据中,或通过网络连接发送到远程机器。

注JSON格式通常被现代应用程序用于数据交换。 许多程序员已经熟悉它,这使它成为互操作性的不错选择。

如果你有一个对象x,你可以用一行简单的代码来查看它的JSON字符串表示:

这里写图片描述

dumps()函数的另一个变体是dump(),能简单地将该对象序列化为文本文件。 因此,如果f是一个为写入而打开的文本文件对象,我们可以这样做:

这里写图片描述

要再次解码该对象,如果f是已打开供阅读的文本文件对象

这里写图片描述

这种简单的序列化技术可以处理列表和字典,但在JSON中序列化任意类实例需要一些额外的努力。 json模块的参考包含对此的解释。

猜你喜欢

转载自blog.csdn.net/u010132497/article/details/80690357
今日推荐