打印格式化,利用这些方法可以让程序的输出看起来与你希望的一样。我们将要了解下面的内容:

  • ˆˆ换行(以及什么时候换行)。
  • ˆˆ水平间隔(以及按列对齐)。
  • ˆˆ在字符串中间打印变量。
  • ˆˆ以整数、小数或E记法格式打印数字,以及设置应当有多少个小数位。

以上应该已经涵盖了程序中需要的 99% 的功能。

换行

  1. print('Hi')
  2. print('There')
  3. Hi
  4. There

除非你另外指出,否则 Python 每次执行 print 时都会在新的一行上开始。打印 Hi 之后,Python 会下移一行,并回到第一列来打印 There。Python 会在两个词之间插入一个换行符(newline)。换行符的作用相当于在文本编辑器中按下了回车。

  1. print('Hi', end = ' ')
  2. print('there')
  3. Hi there
  4. #------------------------
  5. print('Hi')
  6. print()
  7. print('there')
  8. Hi
  9. there

特殊代码

增加换行符还有一种方法。Python 提供了一些特殊的代码,可以把这些代码增加到字符串中,以不同的方式打印。这些特殊的打印代码都以一个反斜线(\)字符开头。换行符的相应代码是 \n :

  1. print("Hello World")
  2. Hello World
  3. print("Hello \nWorld")
  4. Hello
  5. World
  6. print('Hi \nthere')
  7. Hi
  8. there

\n 使 HelloWorld 分别打印在不同的行上,因为它在这两个词之间增加了一个换行符。

如果字符串里面有很多字符都需要转义,就需要加很多 \,为了简化,Python 还允许用 r'' 表示 '' 内部的字符串默认不转义,可以自己试试:

  1. >>> print('\\\t\\')
  2. \ \
  3. >>> print(r'\\\t\\')
  4. \\\t\\

制表符

制表符(Tab, 也叫做进格符)在按列对齐方面非常有用。要了解制表符是如何工作的,可以想一想屏幕上的每一行都划分为多个大小相同的块时是什么样。下面假设每一个块为 8 个字符宽。插人一个制表符时,就会移到下一个块开始的位置。

制表符的特殊代码是 \t,要了解具体怎么做,最好的办法就是试一试。

  1. print('ABC\t\tXYZ')
  2. ABC XYZ

XYZABC 有几个字符的间隔。实际上,XYZ 距离这一行的起始位置正好是 8 个字符。这是因为块的大小是 8。也可以这样讲:每 8 个字符之后有一个制表点(tab stop)。

  1. print('ABC\t\tXYZ')
  2. print('ABCDE\t\tXYZ')
  3. print('ABCEDFG\t\tXYZ')
  4. ABC XYZ
  5. ABCDE XYZ
  6. ABCEDFG XYZ

可以将屏幕(或者每-行)视为按 8 个空格为一块来摆放。注意,尽管 ABC 序列越来越长,但 XYZ 仍保持在原来的位置上。\t 告诉 Python 让 XYZ 从下一个制表点开始,或者从下一个可用的块开始。不过,一旦 ABC 序列长到将第一块填满,Python 就会把 XYZ 下移到下一个制表点。

按列组织内容时,制表符很有用,能让所有内容都对齐。下面就要利用这一点以及我们了解的关于循环的知识,打印一个关于正方形和立方体的表格:

  1. print("Number\tSquare\tCube")
  2. for i in range(1, 11):
  3. print('%d\t\t%d\t\t%d' % (i, i**2, i**3))
  4. Number Square Cube
  5. 1 1 1
  6. 2 4 8
  7. 3 9 27
  8. 4 16 64
  9. 5 25 125
  10. 6 36 216
  11. 7 49 343
  12. 8 64 512
  13. 9 81 729
  14. 10 100 1000

反斜线

由于反斜线字符 \ 用来表示特殊打印代码,如果我们确实想打印一个 \ 字符,而不是将其作为代码的一部分打印,该如何告诉 Python 呢?我们的技巧是把两个反斜线放在一起:

  1. print('hi\\there')
  2. hi\there

第一个 \ 告诉 Python 接下来是一些特殊的内容,第二个 \ 告诉 Python 这些特殊的内容就是 \ 字符。

百分号

百分号(%)对格式字符串来说是一个特殊的字符,那么怎么打印 % 呢?

Python 有时候很聪明,它能确定你什么时候使用号符号开始一个格式字符串,以及什么时候只是想打印一个百分号:

  1. >>> print('I got 90% on my math test!')
  2. I got 90% on my math test!

在这个例子中,字符串外面没有第二个号,也没有需要格式化的变量,所以 Python 认为这个 % 只是字符串中的一个普通字符。

但是如果你在打印格式化字符串时想打印一个百分号,就需要输人两个百分号,就像你曾经用两个反斜线来打印一一个反斜线一样。我们说第一个百分号对第二个百分号进行了转义:

  1. >>> math = 75.4
  2. >>> print('I got %.2f%% on my math test' % math)
  3. I got 75.4% on my math test

第一个 % 表示格式化字符串。两个号在一起告诉 Python,你希望打印出一个 % 字符。引号外面的 % 告诉Python 你需要将后面的变量打印出来。

插入变量

假设希望在 print 语句中间插入一个字符串变量,我们可以使用格式字符串(format string),其中使用了
百分号(号):

  1. name = 'Warren Sande'
  2. book = 'Sky'
  3. print('My name is %s and I wrote this book %s' % (name, book))
  4. My name is Warren Sande and I wrote this book Sky

这里有两处用到号符号。先是用在字符串中间,指示要把变量放在什么位置。然后在字符串后面再次用到,告诉Python 接下来就是我们]希望在字符串中插入的变量。%s 表示我们想插入一个字符串变量。如果想插人整数,要使用 %i;想插入浮点数,则要使用 %f

%s%f%i 都称为格式字符串,这些代码用来指示如何显示变量。格式字符串中还可以增加一些其他内容,从而完全按你希望的方式打印数字。还可以使用一些不同的格式字符串得到类似 E 记法的结果。

如果你想在一个 print 语句中放人多个格式化字符串,该怎么办呢?你可以这样做:

  1. >>> math = 75. 4
  2. >>> science = 82.1
  3. >>> print('I got %.1f in math and %.1f in science' % (math, science))

可以在 print 语句中放入任意多个格式化字符串,后面跟一个变量元组(tuple)。元组和列表很像,只是它使用的是圆括号而不是方括号,而且元组是不可变的。这是 Python 显得很挑剔的一个地方,这里你必须使用元组,而不能使用列表。除非只有一个变量需要格式化,这时才可以不用元组。请确保(引号内的)格式化字符串的数量和(引号外的)变量数量相同,否则程序会报错。

数字格式化

打印数字时,我们希望对数字如何显示有一些控制:

  • 显示多少位小数;
  • 使用常规记法还是 E 记法;
  • 是否增加前导或末尾的 0;
  • 是否在数字前面显示正负号(+或-)。

利用格式字符串,Python 为我们提供了充分的灵活性,不仅可以完成这些工作,甚至还可以做更多事情!

  1. Today's High: 72.45672132, Low: 45.4985756
  2. Today's High: 72, Low: 45

假设我们想要打印一个有两位小数的浮点数:

>>> dec_number = 12.3456
>>> print('It is %.2f degrees today.' % dec_number)
It is 12.35 degrees today

print 语句中间包含一个格式字符串。不过这一次没有直接使用 %f,而是使用了%.2f。这就告诉 Python 要采用浮点数格式,而且小数点后面要显示两位。(注意,Python非常聪明,它会正确地把数字四舍五人为两位小数,而不是直接去掉多余的数位。)

整数:%d 或 %i

要把某项内容打印成整数,可以使用 %d%i 格式字符串。

number = 12.67
>>> print('%i' % number)
12

>>> print(number)
12.67

注意,这一次数字没有四舍五人。它被截断(truncated,表示“直接切断”)了。如果是四舍五人,我们会看到13而不是12。使用整数格式化时,数字会被截断,不过使用浮点数格式化时,数字则会四舍五人。number 的值并没有改变。我们只是使用格式字符串采用不同的方式打印。

这里要注意以下3个方面:

  1. 字符串中不要求有其他文本,可以只包含格式字符串。.
  2. 即使是浮点数,也可以把它打印为整数。这可以通过格式字符串实现。
  3. Python会把值截断为上一个最大整数”。不过,这与 int() 函数不同,因为格式字符串不会像 int() 那样创建一个新的值,而只是改变值显示的方式。

浮点数:%f 或 %F

打印小数时,可以在格式字符串中使用大写或小写的 f (%f%F) :

>>> number = 12.3456
>>> print('%f' % number)
12.345600

如果只使用 %f,数字会显示为有6位小数。如果在 f 前面加上 .n, 这里 n 可以是任意整数,就会把数字四舍五人为指定的小数位数:

>>> print('%.2F' % number)
12.35

可以看到它把数字 12.3456 四舍五人到小数点后前两位:12.35

如果指定的小数位比数中实际的小数位还要多,Python 会用 0 来填充(pad):

>>> print('%8.8f' % number)
12.34560000

这个数的小数点后面只有 4 位,但我们要求有 8 位小数,所以另外 4 位会用 0 来填充。

如果是负数,%f 总会显示 - 号。如果希望数字总会显示正负号(即使它是一个正数),可以在 % 后面加一个 + 号(如果列表中既有正数也有负数,这对于列表的对齐也很有好处):

>>> print('%+f' % number)
+12.345600

如果希望包含正负数的列表对齐,但是不希望看到正数带 + 号,可以在 % 号后面使用一个空格代替 +

>>> number2 = -98.76
>>> print('% .2f' % number2)
-98.76
>>> print('% .2f' % number2)
 12.35

输出中的 12 前面有一个空格,所以,尽管 98 前面有负号而 12 前面没有正负号,这两个数也能对齐。

E记法:%e 或 %E

要使用 e格式 字符串打印 E记法。它总是打印 6 位小数,除非你另作要求。

>>> number = 12. 3456
>>> print('%e' % number)
1.234560e+01

如果要打印更多或更少的小数位,可以在号后面使用 .n,就像打印浮点数时一样:

>>> number = 12. 3456
>>> print('%.3e' % number)
1.235e+01

>>> print('%.8e' % number)
1.23456000e+01

%.3e 四舍五人为3位小数,%.8e 增加了一些 0 来填充不足的小数位。

小写或大写e都是可以的,你在格式字符串中使用什么大小写形式,输出时也会显示同样的大小写:

>>> print('%E' % number)
1.234560E+01

浮点数或E记法:%g 或 %G

如果你希望 Python 自动选择浮点数记法或E记法,可以使用 %g 格式字符串。同样,如果使用大写,输出中就会得到一个大写的E:

>>> number1 = 12.3
>>> number2 = 456712345.6
>>> print('%g' % number1)
>>> print('%g' % number2)

12.3
4.56712e+08

Python 会为大数自动选择E记法,而对较小的数使用浮点数记法。

存储格式化结果

有时你不想直接打印出格式化的数字,而是希望把它存储在一个字符串中以备以后使用。这很容易,可以不打印,把它直接赋给一个变量,如下:

>>> my_string = '%.2f' % 12.3456
>>> print(my_string)
12.35

>>> print('The answer is ' + my_string)
The answer is 12.35

这里没有直接打印格式化数字,我们把它赋给变量 my_string。再将 my_string 与其他一些文本结合,并打印整个句子。

format() 方法

Python 字符串有一个名为 format() 的方法。它的工作方式和在前面见过的 % 格式化字符串很像。事实上,格式化说明符号 f、g、e 等都是一样的,只不过使用方式稍有区别:

math = 80.333
science = 98.20384
print('I got {0:.1f} in math, {1:.1f} in science'.format(math, science))

在这种方法中,格式化说明符被放在花括号中,而不再以 % 开头。0 和 1 告诉 Python 要格式化的是元组中的哪个变量。Python 计数从 0 开始,所以元组中第一个元素(变量 math)的索引是 0,第二个元素(变量 science)的索引是 1。然后使用 .1f

也可以用 % 格式化,将格式化后的字符串存为一个变量:

distance = 149597870700
myString = 'The sun is {0: .4e} meters from the earth'.format(distance)

因为不再使用 % 来区分格式化字符串,所以如果要打印一个 % 的话,也不需要再做任何特殊工作:

>>> print('I got {0:.1f}% in math'.format(math))
I got 87% in math

Padding and aligning

右对齐

'%10s' % ('test',)
'{:>10}'.format('test')
#'      test'


'%4d' % (42,)
'{:4d}'.format(42)
#'  42'


'%04d' % (42,)
'{:04d}'.format(42)
#'0042'


'%06.2f' % (3.141592653589793,)
'{:06.2f}'.format(3.141592653589793)
#'003.14'

左对齐

'%-10s' % ('test',)
'{:10}'.format('test')
#'test      '

'{:_<10}'.format('test')
#'test______'

居中对齐

'{:^10}'.format('test')
#'   test   '

'{:^6}'.format('zip')
#' zip  '

Truncating

.后面的数字决定了截取的长度

'%.5s' % ('xylophone',)
'{:.5}'.format('xylophone')
#'xylop'

对齐、截取结合使用

'%-10.5s' % ('xylophone',)
'{:10.5}'.format('xylophone')
#‘xylop     ’

Signed numbers

'%+d' % (42,)
'{:+d}'.format(42)
#'+42'


'{:=5d}'.format(-23)
#'-  23'


'{:=+5d}'.format(23)
#'+  23'

Placeholders

data = {'first': 'Hello', 'last': 'Hodor!'}
'%(first)s %(last)s' % data
'{first} {last}'.format(**data)
'{first} {last}'.format(first='Hello', last='Hodor!')
'{first} {last}'.format(first=data['first'], last=data['last'])
#'Hello Hodor!'


person = {'first': 'Jean-Luc', 'last': 'Picard'}
'{p[first]} {p[last]}'.format(p=person)
#'Jean-Luc Picard'


data = [4, 8, 15, 16, 23, 42]
'{d[4]} {d[5]}'.format(d=data)
'23 42'

Datetime

from datetime import datetime
'{:%Y-%m-%d %H:%M}'.format(datetime(2021, 2, 3, 4, 5))
#'2021-02-03 04:05'

Parametrized

'{:{align}{width}}'.format('test', align='^', width='10')
#'   test   '


'%.*s = %.*f' % (3, 'Gibberish', 3, 2.7182)
'{:.{prec}} = {:.{prec}f}'.format('Gibberish', 2.7182, prec=3)
#'Gib = 2.718'


'%*.*f' % (5, 2, 2.7182)
'{:{width}.{prec}f}'.format(2.7182, width=5, prec=2)
#' 2.72'


dt = datetime(2021, 2, 3, 4, 5)
'{:{dfmt} {tfmt}}'.format(dt, dfmt='%Y-%m-%d', tfmt='%H:%M')
#'2021-02-03 04:05'


'{:{}{}{}.{}}'.format(2.7182818284, '>', '+', 10, 3)
#'     +2.72'


'{:{}{sign}{}.{}}'.format(2.7182818284, '>', 10, 3, sign='+')
#'     +2.72'

Custom Object

class HAL9000(object):
    def __format__(self, format):
        if (format == 'open-the-pod-bay-doors'):
            return "I'm afraid I can't do that."
        return 'HAL 9000'
    pass

'{:open-the-pod-bay-doors}'.format(HAL9000())
#'I'm afraid I can't do that.'

Revision

  • 如何调整垂直间隔(添加或删除换行符)。
  • 如何用制表符设置水平间隔。
  • 如果使用格式字符串显示不同的数字格式。
  • 使用格式字符串的两种方法: % 符号和 format() 方法。

测试题

  1. 如果有两个单独的 print 语句,如下,怎样把所有内容都打印在同一行上?

    print("What is")
    print("your name?")
    
  2. 打印时如何增加额外的空行?

  3. 实现按列对齐时要使用哪一个特殊打印代码?
  4. 使用哪个格式字符串强制按E记法打印一个数?

动手试一试

  1. 编写一个程序,询问一个人的姓名、年龄和最喜欢的颜色,然后打印在一句话里。运行这个程序时应该看到类似这样的结果:

    What is your name? Sam
    How old are you? 12
    What is your favorite color? green
    Your name is Sam you are 12 years old and you like green
    
  2. 编写一个乘法表程序,使用制表符确保所有内容都能很好地按列对齐。

  3. 编写一个程序计算8的所有分数(例如,1/8, 2/8, 3…..直到8/8),要显示3位小数。