详解 % 号字符串格式化

取模运算符(s % d)可生成格式化的字符串,其中 s 是一个格式字符串,而 d 是一个对象元组或映射对象(字典)。这个运算符的行为类似于 C 语言中的 sprintf() 函数。格式字符串包含两类对象:普通字符(其值不变)和转换说明符,每个转换说明符将被代表相关联元组或映射中元素的格式化字符串代替。如果 d 是一个元组,转换说明符的个数必须与 d 中对象的个数保持一致。如果 d 是一个映射,每个转换说明符都以 % 字符开始,以下表的某个转换字符结尾。

字符 输出格式
d, i 十进制整数或长整数
u 无符号整数或长整数
o 八进制整数或长整数
x 十六进制整数或长整数
X 十六进制整数(大写字母)
f 浮点数,如 [-]m.dddddd
e 浮点数,如 [-]m.dddddde±xx
E 浮点数,如 [-]m.ddddddE±xx
g, G 指数小于 -4 或更高精度时使用 %e 或 %E,否则使用 %f
s 字符串或任意对象。格式化代码使用 str() 生成字符串
r 同 repr() 生成的字符串
c 单个字符
% 字面量 %

在 % 字符和转换字符之间,可以出现以下修饰符,并且只能按照以下顺序出现。

  1. 位于括号中的一个键名,用于从映射对象中选出一个具体项。如果不存在此类元素,就会引发 KeyError 异常。
  2. 下面所列的一个或多个。
    • -,左对齐标志。默认值为右对齐。
    • +,表示应该包含数值符号(即使为正值也是如此)。
    • 0,表示一个零填充。
  3. 一个指定最小自动宽度的数。转换后的值将被打印在至少为这个宽度的字段中,并且在左边填充至满字段宽(如果指定了 - 标志,则填充在右边)
  4. 一个小数点,用于按照精度分割字段宽度。
  5. 一个数,指定要打印字符串中的最大字符个数,浮点数中小数点之后的位数,或者整数的最小位数。

另外,星号(*)字符用于在任意宽度的字段中替换数。如果存在,宽度将从元组的下一项中读出。

下面的代码给出了一些例子:

a = 42
b = 13.142783
c = "hello"
d = {'x': 13, 'y': 1.54321, 'z': 'world'}
e = 5628398123741234
r = "a is %d" % a            # r = "a is 42"
r = "%10d %f" % (a, b)       # r = "        42 13.142783"
r = "%+010d % E" % (a, b)    # r = "+000000042  1.314278E+01"
r = "%(x)-10d %(y)0.3g" % d  # r = "13         1.54"
r = "%0.4s %s" % (c, d['z']) # r = "hell world"
r = "%*.*f" % (5, 3, b)      # r = "13.143"
r = "e = %d" % e             # r = "e = 5628398123741234"

和字典一起使用时,字符串格式化运算符 % 通常用于模仿在脚本语言中常见的插值(interpolation)功能(如字符串中 $var 符号的扩展)。例如,如果你有一个包含数个值的字典,那么你可以在格式化字符串中把这些值扩展到字段中。

stock = {
    'name' : 'GOOG',
    'shares' : 100,
    'price' : 490,10}
	
r = "%(shares)d of %(name)s at %(price)0.2f" % stock
# r = "100 of GOOG at 490.10"

下面的代码说明了如何将当前定义变量的值扩展到一个字符串中。调用 vars() 函数时,它将返回一个包含此时已定义的所有变量的字典。

name = "Elwood"
age = 41
r = "%(name)s is %(age)d years old" vars()
r = "Elwood is 41 years old"