多年来,Python 具有出色的字符串格式化程序,但是有关它们的文档在理论和技术上都太过严格了。通过此站点,我们尝试通过实际示例向您展示新旧风格的字符串格式化 API 涵盖的最常见的用例。
此页面上的所有示例均可与 Python 2.7、3.2、3.3、3.4 和 3.5 一起使用,而无需任何额外的库。
基本的格式化
简单的位置格式化可能是最常见的用例。如果参数的顺序不太可能改变,并且只有很少的元素要连接,可以采用这样的格式化风格。
由于元素没有像名称一样具有描述性,因此这个简单的风格仅应用于格式化相对少量的元素。
Old | '%s %s' % ('one', 'two') |
New | '{} {}'.format('one', 'two') |
Output | one two |
Old | '%d %d' % (1, 2) |
New | '{} {}'.format(1, 2) |
Output | 1 2 |
使用新的格式化风格(在 Python 2.6 中甚至是强制性的),可以为占位符提供显式的位置索引。
这允许在不更改参数的情况下重新排列显示顺序。
此操作不适用于旧的格式化风格。
New | '{1} {0}'.format('one', 'two') |
Output | two one |
值转换
新的简单格式化器默认调用对象的 __format__() 方法来呈现它。如果你只想呈现 str(…) 或 repr(…) 的输出,你可以使用 !s 或 !r 转换标志。
class Data(object):
def __str__(self):
return 'str'
def __repr__(self):
return 'repr'
Old | '%s %r' % (Data(), Data()) |
New | {0!s} {0!r}'.format(Data()) |
Output | str repr |
在 Python 3 中,存在一个附加的转换标志,该标志使用 repr(…) 的输出,但使用 ascii(…) 代替。
class Data(object):
def __repr__(self):
return 'räpr'
Old | '%r %a' % (Data(), Data()) |
New | '{0!r} {0!a}'.format(Data()) |
Output | räpr r\xe4pr |
填充和对齐字符串
默认情况下,将值格式化为仅表示内容所需的字符。但是,也可以将值填充到特定的长度。
不幸的是,新旧格式化风格之间的默认对齐方式有所不同。旧风格的默认为右对齐,而新风格的则为左对齐。
右对齐:
Old | '%10s' % ('test',) |
New | '{:>10}'.format('test') |
Output | test |
左对齐:
Old | '%-10s' % ('test',) |
New | '{:10}'.format('test') |
Output | test |
同样,通过提供对值的填充和对齐方式的更多控制,新的格式化风格超越了旧的。
你可以选择填充字符:
此操作不适用于旧的格式化风格。
New | '{:_<10}'.format('test') |
Output | test______ |
还可以居中对齐值:
此操作不适用于旧的格式化风格。
New | '{:^10}'.format('test') |
Output | test |
当使用居中对齐时,如果字符串的长度导致填充字符的不均匀分割,则多余的字符将被放在右侧:
此操作不适用于旧的格式化风格。
New | '{:^6}'.format('zip') |
Output | zip |
截断长串
与填充相反,也可以将过长的值截断成特定数量的字符。
在格式字符串中点 (.) 后面的数字指定了输出的精度。对于字符串,这意味着输出将被截断为指定的长度。在示例中,这是 5 个字符。
Old | '%.5s' % ('xylophone',) |
New | '{:.5}'.format('xylophone') |
Output | xylop |
结合截断与填充
Old | '%-10.5s' % ('xylophone',) |
New | '{:10.5}'.format('xylophone') |
Output | xylop |
数字
当然,也可以格式化数字。
整数:
Old | '%d' % (42,) |
New | '{:d}'.format(42) |
Output | 42 |
浮点数:
Old | '%f' % (3.141592653589793,) |
New | '{:f}'.format(3.141592653589793) |
Output | 3.141593 |
填充数字
与字符串相似,数字也可以被限制为特定的宽度。
Old | '%4d' % (42,) |
New | '{:4d}'.format(42) |
Output | 42 |
同样,类似于截断字符串,浮点数的精度限制了小数点后的位数。
对于浮点数,填充值表示完整输出的长度。在下面的示例中,我们希望输出至少有 6 个字符,包括小数点后的 2 个字符。
Old | '%06.2f' % (3.141592653589793,) |
New | '{:06.2f}'.format(3.141592653589793) |
Output | 003.14 |
对于整数值,提供精度没有多大意义,实际上在新的风格中是被禁止的(这将导致 ValueError)。
Old | '%04d' % (42,) |
New | '{:04d}'.format(42) |
Output | 0042 |
带符号的数字
默认情况下,只有负数带有符号。这当然可以更改。
Old | '%+d' % (42,) |
New | '{:+d}'.format(42) |
Output | +42 |
使用空格字符表示负数应以减号开头,正数应以前导空格开头。
Old | '% d' % ((- 23),) |
New | '{: d}'.format((- 23)) |
Output | -23 |
Old | '% d' % (42,) |
New | '{: d}'.format(42) |
Output | 42 |
新的格式化风格还能够控制符号相对于填充字符的位置。
此操作不适用于旧的格式化风格。
New | '{:=5d}'.format((- 23)) |
Output | - 23 |
New | '{:=+5d}'.format(23) |
Output | + 23 |
有名字的占位符
两种格式化风格都支持有名字的占位符。
data = {'first': 'Hodor', 'last': 'Hodor!'}
Old | '%(first)s %(last)s' % data |
New | '{first} {last}'.format(**data) |
Output | Hodor Hodor! |
.format() 也接受关键字参数(keyword arguments)。
此操作不适用于旧的格式化风格。
New | '{first} {last}'.format(first='Hodor', last='Hodor!') |
Output | Hodor Hodor! |
Getitem 和 Getattr
新的格式化风格在访问嵌套的数据结构时提供了更大的灵活性。
它支持访问支持 __getitem__ 的容器,例如字典和列表:
此操作不适用于旧的格式化风格。
person = {'first': 'Jean-Luc', 'last': 'Picard'}
New | '{p[first]} {p[last]}'.format(p=person) |
Output | Jean-Luc Picard |
data = [4, 8, 15, 16, 23, 42]
New | '{d[4]} {d[5]}'.format(d=data) |
Output | 23 42 |
以及通过 getattr() 访问对象的属性:
此操作不适用于旧的格式化风格。
class Plant(object):
type = 'tree'
New | '{p.type}'.format(p=Plant()) |
Output | tree |
两种类型的访问都可以自由混合和任意嵌套:
此操作不适用于旧的格式化风格。
class Plant(object):
type = 'tree'
kinds = [{'name': 'oak'}, {'name': 'maple'}]
New | '{p.type}: {p.kinds[0][name]}'.format(p=Plant()) |
Output | tree: oak |
日期时间
新的格式化风格还允许对象控制自己的呈现。例如,这允许在格式字符串中将日期时间对象格式化:
此操作不适用于旧的格式化风格。
from datetime import datetime
New | '{:%Y-%m-%d %H:%M}'.format(datetime(2001, 2, 3, 4, 5)) |
Output | 2001-02-03 04:05 |
参数化的格式
此外,新的格式化风格允许使用参数动态地指定格式字符串的所有组成部分。参数化的格式字符串是括号中的嵌套表达式,可以在冒号之后的父格式中的任何位置出现。
旧的格式化风格也支持某些参数化,但受到更多的限制。即它仅允许对输出的宽度和精度进行参数化。
参数化的对齐方式和宽度:
此操作不适用于旧的格式化风格。
New | '{:{align}{width}}'.format('test', align='^', width='10') |
Output | test |
参数化的精度:
Old | '%.*s = %.*f' % (3, 'Gibberish', 3, 2.7182) |
New | '{:.{prec}} = {:.{prec}f}'.format('Gibberish', 2.7182, prec=3) |
Output | Gib = 2.718 |
宽度和精度:
Old | '%*.*f' % (5, 2, 2.7182) |
New | '{:{width}.{prec}f}'.format(2.7182, width=5, prec=2) |
Output | 2.72 |
嵌套格式可用于替换格式中的任何部分,因此上述精度示例可以重写为:
此操作不适用于旧的格式化风格。
New | '{:{prec}} = {:{prec}}'.format('Gibberish', 2.7182, prec='.3') |
Output | Gib = 2.72 |
日期和时间可以分别设置:
此操作不适用于旧的格式化风格。
from datetime import datetime
dt = datetime(2001, 2, 3, 4, 5)
New | '{:{dfmt} {tfmt}}'.format(dt, dfmt='%Y-%m-%d', tfmt='%H:%M') |
Output | 2001-02-03 04:05 |
嵌套格式可以是位置参数。位置取决于花括号的顺序:
此操作不适用于旧的格式化风格。
New | '{:{}{}{}.{}}'.format(2.7182818284, '>', '+', 10, 3) |
Output | +2.72 |
当然,可以像之前那样混合使用关键字参数:
此操作不适用于旧的格式化风格。
New | '{:{}{sign}{}.{}}'.format(2.7182818284, '>', 10, 3, sign='+') |
output | +2.72 |
自定义对象
datetime 示例通过使用 __format__() 这个神奇的方法来工作。你可以在自己的对象中通过重写此方法以定义自己的格式处理方式。这使你可以完全控制所使用的格式语法。
此操作不适用于旧的格式化风格。
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'
New | '{:open-the-pod-bay-doors}'.format(HAL9000()) |
Output | I’m afraid I can’t do that. |