字符串格式化之format()
字符串的格式化是特别特别重要的一个知识点,自己将通过python官方文档来具体总结学习它,整体为如下一篇笔记文章,以备自己后来复习回顾。
一、format()
在官方文档的整体介绍:
-
python官网的原文如下:
-
关于上述话的理解翻译
- 这第一段话的意思是说:将我们需要输出的值通过
format_spec
处理之后格式化打印输出,关于format_spec
的解释取决于value
参数的类型。但是呢,大多数内置类型都使用标准的格式语法叫做:格式规范迷你语言(Format Specification Mini-Language) - 第二段话的意思是:默认的
format_spec
是一个空的字符串“”
,其效果通常与调用str(value)
的效果是相同的。 - 第三段话的意思是:在搜索值的
__format__()
方法的时候,通常会绕开实例字典将format(value,format_spec)
转换成type(value).__format__(value, format_spec)
的形式。如果该方法搜索到一个对象并且该对象format_spec
为非空,或者说如果format_spec
其返回值不是一个字符串,则会引发TypeError异常。 - 关于改版的异常处理这里将其省略。
- 这第一段话的意思是说:将我们需要输出的值通过
二、format()
语法在官方文档的介绍
-
那么
format()
的语法我们该如何来用呢?下面是format()
的语法在官网的介绍原文如下:
-
理解翻译如下:
-
第一段话的意思如下:格式字符串包含由大括号
{}
包围的“替换字段”。大括号未包含的任何内容都被视为文字文本,并将其原样的复制到输出中。如果需要在文字文本中包含大括号字符,可以通过加倍的{{
和}}
来对其进行转义。 -
下面的表格就是替换字段的语法
-
第三段:用不太正式的语言来说,替换字段
replacement_field
可以用上述表格中的语法格式[field_name]
开头,这个[field_name]
就是需要指定格式化的值,并且将该值插入到输出的对象中去来代替前面我们需要替换的替换字段replacement_field
。 在[field_name]
随后跟着一个前面带有感叹号!
的转换字段conversion
和带有冒号:
的格式化形式format_spec
。它们为替换值指定非默认格式。 -
第四段:
field_name
本身是以数字或者关键字的arg_name
开头。如果它是数字,它指的是一个位置参数;如果它是关键字,那么它指的是一个命名的关键字参数。如果格式字符串中的数字arg_name
依次为0、1、2、…,则可以省略它们(而不仅仅是省略其中的一些),数字0、1、2、…将按顺序自动插入。由于arg_name
不是用引号分隔的,因此无法在格式字符串中指定任意的字典键(例如,字符串“10”,或“:-]”)。arg_name
后面可以跟任意数量的索引或者属性表达式。形为".name"
的表达式使用getattr()
方法选择命名属性,而形式为[index]
的表达式使用__getitem__()
执行索引查找。 -
关于改版的说明在这里做省略。
-
下面的表格是一些简例。
-
倒数第二段:转换字段
conversion
在格式化之前会导致强制类型转换。通常格式化值的工作由值本身的__format__()
方法完成的。然而在某些情况下,需要强制将类型格式化为字符串,来重写它自身的格式定义。通过在调用__format__()
之前将值转换为字符串,绕过正常的本身__format__()
格式化逻辑。目前支持三个转换标志:!s
将会对值调用str()
方法,!r
将会调用repr()
方法,以及!a
将会调用ascii()
方法。 -
注释:
repr()
方法:repr()
函数将对象转化为供解释器读取的形式。
测试代码:
# coding=UTF-8 s="物品\t单价\t数量\n包子\t1\t2" print(s) print(repr(s))
运行结果:
物品 单价 数量 包子 1 2 '物品\t单价\t数量\n包子\t1\t2'
ascii()
方法:ascii()
函数类似repr()
函数, 返回一个表示对象的字符串, 但是对于字符串中的非 ASCII 字符则返回通过repr()
函数使用 \x, \u 或 \U 编码的字符。 生成字符串类似 Python2 版本中repr()
函数的返回值。
测试代码:
>>> ascii('runoob') "'runoob'"
-
三、format_spec
格式化迷你语言
下面是关于Format Specification Mini-Language的python官方文档,接下来通过分析官方文档来学习format()
格式化字符串中的Format Specification Mini-Language。
- 下面是官网中的原文:
-
理解翻译:
- 下面这是第一段话的解释: 在
format(value, format_spec="")
中format_spec
相当于Format Specifications
的简称。我们需要格式化字符串时需要用format_spec
来规范如何显示我们输出的字符串。 - 第二段话的解释为: 有些格式选项只支持数字类型
- 第三段话解释:一般惯例是,空格式规范
format_spec
产生的结果与对值调用str()
时的结果相同。 非空的 格式化规范format_spec
通常会修改解果。 - 接下来是一个语法表格
- 第四段话是:如果指定了一个有效的对齐值,则可以在其前面加一个填充字符,该字符可以是任意字符,如果填充字符被省略,则默认为空格。在格式化字符串文本中使用
str.format()
方法时,不能使用文本大括号("{"
或"}"
)作为填充字符。但是,我们可以插入带有 替换字段repacement_field
的大括号"{ }"
({{}}
)。因此这个限制不会影响我们对format()
方法的使用。
- 下面这是第一段话的解释: 在
-
关于
format_spec
中的[align]
选项如下:
关于上述表格对应中文表格如下:
选项 描述 <
强制字段在有效空间内保持左对齐(这是大多数对象的默认设置) >
强制字段在有效空间内保持右对齐(这是大多数对象的默认设置) =
强制将填充字符放置在符号(如果有)之后数字之前,这被用来打印例如表单“+000000120”这样的字段。并且这种对齐选项仅对数字类型有效。当“0”紧接在字符宽度之前时,它将成为填充数字时的默认值。 ^
强制字段在有效空间内保持居中对齐 -
关于
format_spec
中的[sign]
选项如下:
该[sign]
选项只对数字类型有效
关于上述表格的对应中文表如下:选项 描述 +
表示正负数均可使用符号 -
指示符号只被用于负数(这是默认行为) space
表示正数应使用前导空格,负数应使用负号。 -
下面是关于
format_spec
中的[z]
选项的解释
选项 | 描述 |
---|---|
z | “z”选项在舍入到格式精度后将负零浮点值强制为正零。此选项仅对浮点表示类型有效。 |
- 关于
format_spec
中的#
的解释
选项 | 描述 |
---|---|
# | #号这个选项仅对整型、浮点型和负数型有效。对于整数,当使用二进制、八进制或十六进制输出时,此选项会在输出值中添加相应的前缀"0b" 、"0o" 、"0x" 或"0X" 。对于浮点型和负数型,即使后面没有数字,替换形式会导致转换结果始终包含小数点字符,但通常,只有数字跟在小数点字符后面时,小数点字符才会出现在这些转换的结果中。此外,对于“g”和“G”的科学计数法小数点的转换,不会从结果中删除尾随零。 |
- 关于
format_spec
中的[0]
[width]
的解释
选项 | 描述 |
---|---|
[0] 和[width] | width是定义最小字段总宽度的十进制整数,包括任何前缀、分隔符和其他格式字符。如果未指定,则字段宽度将由输出内容决定。如果未指定显式对齐方式,则在宽度字段前面加一个零(“0” )字符将启用数字类型的符号识别零填充。这相当于对齐类型[sign] 为“=” 的填充字符“0” 。 |
- 关于
format_spec
中的[grouping_option]
的解释
选项 | 描述 |
---|---|
, | “,” 选项表示使用逗号作为千位分隔符。对于支持区域设置的分隔符,请改用“n”整数表示类型。 |
_ | “_” 选项表示对浮点表示类型和整数表示类型“d” 使用下划线作为千位分隔符。对于整数表示类型“b” 、“o” 、“x” 和“x” ,将每4位插入下划线。对于其他演示类型,指定此选项是错误的。 |
- 关于
format_spec
中的[.precision]
的解释
.precision | 精度是一个十进制整数,表示浮点类型“f” 和“f” 的小数点之后应显示多少位数字,表示科学计数法小数类型“g” 或“g” 的小数点前和后应显示多少位数。对于字符串类型,字段指示最大字段大小,换句话说,字段内容将使用多少个字符。整数表示类型不允许精度。 |
-
关于
format_spec
中的[type]
类型的解释- 关于字符串表示类型
类型 含意 's'
字符串格式。这是字符串的默认类型,可以省略。 None
和 's'
一样。- 关于整数表示类型
类型 含意 'b'
二进制格式。 输出以 2 为基数的数字。 ' c'
将字符在打印之前将整数转换为相应的unicode字符。 'd'
十进制整数。 输出以 10 为基数的数字。 'o'
八进制格式。 输出以 8 为基数的数字。 'x'
十六进制格式。 输出以 16 为基数的数字,使用小写字母表示 9 以上的数码。 'X'
十六进制格式。 输出以 16 为基数的数字,使用大写字母表示 9 以上的数码。 在指定 ‘#’ 的情况下,前缀 '0x'
也将被转为大写形式'0X'
。'n'
数字。 这与 'd'
相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。None
和 'd'
相同。- 在上述的表示类型之外,整数还可以通过下列的浮点表示类型来格式化 (除了
'n'
和None
)。 当这样做时,会在格式化之前使用float()
将整数转换为浮点数。
类型 含意 'e'
科学计数法。 对于一个给定的精度 p
,将数字格式化为以字母'e'
分隔系数和指数的科学计数法形式。 系数在小数点之前有一位,之后有p
位,总计p + 1
个有效数位。 如未指定精度,则会对float
采用小数点之后6
位精度,而对Decimal
则显示所有系数位。 如果小数点之后没有数位,则小数点也会被略去,除非使用了#
选项。'E'
科学计数法。 与 'e'
相似,不同之处在于它使用大写字母'E'
作为分隔字符。'f'
定点表示法。 对于一个给定的精度 p
,将数字格式化为在小数点之后恰好有p
位的小数形式。 如未指定精度,则会对float
采用小数点之后6
位精度,而对Decimal
则使用大到足够显示所有系数位的精度。 如果小数点之后没有数位,则小数点也会被略去,除非使用了#
选项。'F'
定点表示。 与 'f'
相似,但会将nan
转为NAN
并将inf
转为INF
。'g'
1. 常规格式。 对于给定精度 p >= 1
,这会将数值舍入到p
个有效数位,再将结果以定点表示法或科学计数法进行格式化,具体取决于其值的大小。 精度0
会被视为等价于精度1
。2.准确的规则如下: 假设使用表示类型'e'
和精度p-1
进行格式化的结果具有指数值exp
。 那么如果m <= exp < p
,其中m
以-4
表示浮点值而以-6
表示Decimal
值,该数字将使用类型'f'
和精度p-1-exp
进行格式化。 否则的话,该数字将使用表示类型'e'
和精度p-1
进行格式化。 在两种情况下,都会从有效数字中移除无意义的末尾零,如果小数点之后没有余下数字则小数点也会被移除,除非使用了'#'
选项。3.如未指定精度,会对float
采用 6 个有效数位的精度。 对于Decimal
,结果的系数会沿用原值的系数数位;对于绝对值小于1e-6
的值以及最小有效数位的位值大于1
的数值将会使用科学计数法,在其他情况下则会使用定点表示法即科学计数法。正负无穷,正负零和nan
会分别被格式化为inf
,-inf
,0
,-0
和nan
,无论精度如何设定。'G'
常规格式。 类似于 'g'
,不同之处在于当数值非常大时会切换为'E'
。 无穷与NaN
也会表示为大写形式。'n'
数字。 这与 'g'
相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。'%'
百分比。 将数字乘以 100 并显示为定点 ( 'f'
) 格式,后面带一个百分号。None
对于 float
来说这类似于'g'
,不同之处在于当使用定点表示法时,小数点之后将至少显示一位。 所用的精度会大到足以精确表示给定的值。对于Decimal
来说这相当于'g'
或'G'
,具体取决于当前decimal
上下文的context.capitals
值。总体效果是将str()
的输出匹配为其他格式化因子所调整出的样子。
四、关于format()
格式化实例的一些应用
format()
语法在大多数情况下与旧式的 %
格式化类似,只是增加了 {}
和 :
来取代 %
。 例如'%03.2f'
可以被改写为 '{:03.2f}'
。
新的格式语法还支持新增的不同选项,将在以下示例中说明。
- 按位置访问参数:
>>>'{0}, {1}, {2}'.format('a', 'b', 'c')
'a, b, c'
>>>'{}, {}, {}'.format('a', 'b', 'c') # 3.1+ only
'a, b, c'
>>>'{2}, {1}, {0}'.format('a', 'b', 'c')
'c, b, a'
>>>'{2}, {1}, {0}'.format(*'abc') # unpacking argument sequence 序列解包
>>>'c, b, a'
'{0}{1}{0}'.format('abra', 'cad') # arguments' indices can be repeated 参数索引重复
'abracadabra'
- 按名称访问参数
>>>'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
'Coordinates: 37.24N, -115.81W'
>>>coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
>>>'Coordinates: {latitude}, {longitude}'.format(**coord)
'Coordinates: 37.24N, -115.81W'
- 访问参数的属性
>>>c = 3-5j
>>>('The complex number {0} is formed from the real part {0.real} ''and the imaginary part {0.imag}.').format(c)
'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.'
>>>class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __str__(self):
return 'Point({self.x}, {self.y})'.format(self=self)
>>>str(Point(4, 2))
'Point(4, 2)'
- 访问参数的项
>>>coord = (3, 5)
>>>'X: {0[0]}; Y: {0[1]}'.format(coord)
'X: 3; Y: 5'
- 替代
%s
和%r
:
>>>"repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
"repr() shows quotes: 'test1'; str() doesn't: test2"
- 对齐文本以及指定宽度:
>>>'{:<30}'.format('left aligned')
'left aligned '
>>>'{:>30}'.format('right aligned')
' right aligned'
>>>'{:^30}'.format('centered')
' centered '
>>>'{:*^30}'.format('centered') # use '*' as a fill char
'***********centered***********'
- 替代 %+f, %-f 和 % f 以及指定正负号:
>>>'{:+f}; {:+f}'.format(3.14, -3.14) # show it always 正负号都显示
'+3.140000; -3.140000'
>>>'{: f}; {: f}'.format(3.14, -3.14) # show a space for positive numbers 只显示正号的空格
' 3.140000; -3.140000'
>>>'{:-f}; {:-f}'.format(3.14, -3.14) # show only the minus -- same as '{:f}; {:f}' 只显示负数的负号
'3.140000; -3.140000'
- 替代 %x 和 %o 以及转换基于不同进位制的值:
>>># format also supports binary numbers
>>>"int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)
'int: 42; hex: 2a; oct: 52; bin: 101010'
>>># with 0x, 0o, or 0b as prefix:
>>>"int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin:{0:#b}".format(42)
'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'
- 使用逗号作为千位分隔符:
>>>'{:,}'.format(1234567890)
'1,234,567,890'
- 表示为百分数:
>>>points = 19
>>>total = 22
>>>'Correct answers: {:.2%}'.format(points/total)
'Correct answers: 86.36%'
- 使用特定类型的专属格式化:
>>>import datetime
>>>d = datetime.datetime(2010, 7, 4, 12, 15, 58)
>>>'{:%Y-%m-%d %H:%M:%S}'.format(d)
'2010-07-04 12:15:58'
- 嵌套参数以及更复杂的示例:
>>>for align, text in zip('<^>', ['left', 'center', 'right']):
'{0:{fill}{align}16}'.format(text, fill=align, align=align)
'left<<<<<<<<<<<<'
'^^^^^center^^^^^'
'>>>>>>>>>>>right'
>>>
>>>octets = [192, 168, 0, 1]
>>>'{:02X}{:02X}{:02X}{:02X}'.format(*octets)
'C0A80001'
>>>int(_, 16)
3232235521
>>>
>>>width = 5
>>>for num in range(5,12):
for base in 'dXob':
print('{0:{width}{base}}'.format(num, base=base, width=width), end=' ')
print()
5 5 5 101
6 6 6 110
7 7 7 111
8 8 10 1000
9 9 11 1001
10 A 12 1010
11 B 13 1011