【译】格式字符串语法

前言:本文由Python 3.5.2 Documentation部分章节翻译整理而来

1 >> Format String Syntax

str.format()方法和Formatter类共享相同的格式字符串语法(虽然在Formatter这种情况下,子类可以定义它们自己的格式字符串语法)。

格式字符串包含由大括号{}括起来的“替换字段”,不被包含在大括号内的任何内容被视作文字文本,它不做更改地复制到输出中。如果你需要在文字文本中包含大括号字符,可以通过两个大括号转义:{{and}}

替换字段的语法如下:

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
arg_name          ::=  [identifier | integer]
attribute_name    ::=  identifier
element_index     ::=  integer | index_string
index_string      ::=  <any source character except "]"> +
conversion        ::=  "r" | "s" | "a"
format_spec       ::=  <described in the next section>

在较不正式的术语中,替换字段可以以field_name开始,该字段指定了要对其值进行格式化并插入输出而不是替换字段的对象。field_name后面紧跟一个转换字段conversion,其前面带有一个感叹号format_spec,其前面带有冒号:,它们为替换值指定非非默认格式。

另请参阅Format Specification Mini-Language部分。

field_name自身以arg_name开头,它是一个数字或者关键字。如果它是一个数字,它指的是一个位置参数,如果它是一个关键字,它指的是一个命名的关键字参数。如果格式字符串中的数字arg_names按顺序为0,1,2,...,它们都可以省略(不只是一些),并且数字0,1,2,...将以该顺序自动插入 。 因为arg_name不是引号分隔的,所以不能在格式字符串中指定任意字典键(例如,字符串'10'或':- ]')。arg_name后面可以跟任意数量的索引或属性表达式。 形如'.name'的表达式使用getattr()选择命名属性,而'[index]'形式的表达式使用__getitem __()进行索引查找。

在版本3.1中的更改:可以省略位置参数说明符,因此'{}{}'等价于'{0}{1}'

一些简单的格式化字符串的示例:

"First, thou shalt count to {0}"  # References first positional argument
"Bring me a {}"                   # Implicitly references the first positional argument
"From {} to {}"                   # Same as "From {0} to {1}"
"My quest is {name}"              # References keyword argument 'name'
"Weight in tons {0.weight}"       # 'weight' attribute of first positional arg
"Units destroyed: {players[0]}"   # First element of keyword argument 'players'.

conversion字段在格式化之前引起类型强制。 通常,格式化值的工作是通过值本身的__format __()方法来完成的。 然而,在某些情况下,希望强制类型被格式化为字符串,覆盖其自己的格式化定义。 通过在调用__format __()之前将值转换为字符串,将绕过正常的格式化逻辑。

目前支持三个转换标志:'!s',在值上调用str(),'!r'调用repr()和'!a'调用ascii()。

一些示例:

"Harold's a clever {0!s}"        # Calls str() on the argument first
"Bring out the holy {name!r}"    # Calls repr() on the argument first
"More {!a}"                      # Calls ascii() on the argument first

format_spec字段包含了如何呈现值的规范,包括诸如字段宽度,对齐方式,填充,小数精度等详细信息。 每个值类型都可以定义自己的“格式化迷你语言”或format_spec的解释。

大多数内置类型支持通用格式化迷你语言,这将在下一节中描述。

format_spec字段还可以在其中包括嵌套的替换字段。 这些嵌套替换字段可能包含字段名称,转换标志和格式规范,但不允许更深的嵌套。format_spec中的替换字段在解释format_spec字符串之前被替换。 这允许动态指定值的格式。

参阅Format examples部分获取一些示例。

1.1 >> Format Specification Mini-Language

“格式规范”用于包含格式字符串的替换字段中,它定义如何显示各个值(请参阅Format String Syntax)。 它们也可以直接传递到内置函数format()中。 每个格式类型可以定义如何解释格式规范。

大多数内置类型实现了以下选项的格式规范,尽管某些格式化选项仅支持数字类型。

一般约定,空格式字符串("")产生的结果与在值上调用str()的结果相同。 非空格式字符串通常会修改结果。

标准格式说明符的一般形式是:

format_spec ::=  [[fill]align][sign][#][0][width][,][.precision][type]
fill        ::=  <any character>
align       ::=  "<" | ">" | "=" | "^"
sign        ::=  "+" | "-" | " "
width       ::=  integer
precision   ::=  integer
type        ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

如果指定了有效的align值,它可以在fill字符前面,该fill字符可以是任何字符,如果省略,则默认为空格。 使用str.format()方法时,不能使用字面大括号(“{”或“}”)作为填充字符。 但是,可以插入具有嵌套替换字段的大括号。 此限制不会影响format()函数。

各种对齐选项的含义如下:

选 项 含义
< 强制该字段在可用空间内左对齐(这是大多数对象的默认值)。
> 强制该字段在可用空间内右对齐(这是数字的默认值)。
=

强制将填充放置在符号(如果有)之后但在数字之前。 这用于打印形如“+000000120”的字段。 此对齐选项仅对数字类型有效。 当'0'紧接在字段宽度之前时,它变为默认值。

^ 强制字段在可用空间中居中。

注意,除非定义了最小字段宽度,否则字段宽度将始终与填充数据的大小相同,因此在这种情况下,对齐选项没有意义。

sign选项仅对数字类型有效,可以是以下之一:

选项 含义
+ 表示正数和负数都应使用此符号。
- 表示符号应仅用于负数(这是默认行为)。
space 表示在正数上使用前导空格,在负数上使用负号。

”选项会使“替代形式”用于转换。不同类型的替代形式定义不同。此选项仅对整数,浮点数,复数和小数类型有效。对于整数,当使用二进制,八进制或十六进制输出时,此选项将相应的前缀“0b”,“0o”或“0x”添加到输出值。对于浮点数,复数和小数,替代形式导致转换结果始终包含小数点字符,即使后面没有数字。通常,只有在数字跟在后面,这些转换的结果才会出现小数点字符。此外,对于“g”和“G”转换,结果中不会删除尾随零。

''选项表示使用逗号作为千位分隔符。对于区域设置感知分隔符,请改用“n”整数表示类型。

在版本3.1中更改:添加了','选项(另请参见PEP 378)。

width是定义最小字段宽度的十进制整数。如果未指定,则字段宽度将由内容确定。

当没有给出明确的对齐方式时,在width字段之前用零(“0”)字符启用数字类型的符号感知填零。这相当于一个带0的fill字符,对齐类型为'='。

precision是一个十进制数,表示对于使用'f'和'F'格式化的浮点值,小数点后应显示多少位数,对于使用'g'或'G'格式化的浮点值,小数点前后应显示多少位数; 对于非数字类型,字段表示最大字段大小---换句话说,将从字段内容中使用多少字符。整数值不允许precision

最后,type决定如何显示数据。

可用的字符串表示类型有:

类型 含义
s 字符串格式。 这是字符串的默认类型,可以省略
None 与s相同

可用的整数表示类型有:

类型 含义
b 二进制格式。 输出基数2中的数字。
c 字符。 在打印之前将整数转换为相应的unicode字符。
d 小数整数。 输出基数10中的数字。
o 八进制格式。 输出基数8中的数字。
x 十六进制格式。 输出基数16中的数字,对于9以上的数字使用小写字母。
X 十六进制格式。 输出基数16中的数字,使用大写字母表示9以上的数字。
n 数。 这与“d”相同,除了它使用当前语言环境设置插入适当的数字分隔符字符。
None 与“d”相同。

除了上述表示类型,整数可以用下面列出的浮点表示类型格式化(除了“n”和“None”)。 这样做时,float()用于在格式化之前将整数转换为浮点数。

可用的浮点值和小数值的表示类型有:

类型 含义
e 指数符号。以科学记数法打印数字,使用字母“e”表示指数。默认精度为6。
E 指数符号。与'e'相同,除了它使用大写字母“E”作为分隔符。
f 固定点。显示定点编号。默认精度为6。
F 固定点。与'f'相同,但将nan转换为NAN,将inf转换为INF。
g

一般格式。对于给定精度p> = 1,将数字四舍五入为p个有效数字,然后根据其大小以固定点格式或科学记数法格式化结果。

精确的规则如下:假设以表示类型“e”和精度p-1格式化的结果将具有指数exp。然后,如果-4 <= exp <p,则数字被格式化为呈现类型“f”和精度p-1-exp。否则,数字格式化为显示类型“e”和精度p-1。在这两种情况下,从有效位数中删除无意义的尾部零,如果没有剩余的数字,小数点也将被删除。

无论精度如何,正负无穷大,正负零,和nans分别格式化为inf,-inf,0,-0和nan。

精度为0被视为相当于精度为1.默认精度为6。

G 一般格式。与“g”相同,但如果数字过大,则切换到“E”。无穷大和NaN的表示也是大写的。
n 数字。这与“g”相同,除了它使用当前语言环境设置插入适当的数字分隔符字符。
% 百分比。将数字乘以100,并以固定('f')格式显示,后跟百分比符号。
None 与'g'类似,除了定点符号使用时,至少有一个数字超过小数点。默认精度与表示特定值所需的精度一样高。总体效果是匹配由其他格式修改器改变的str()的输出。


1.2 >> Format examples

本节包含str.format()语法的示例和与旧的%格式的比较。

在大多数情况下,语法类似于旧的%格式,添加了{}和with:用于替代%。 例如,'%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

2 >> printf-style String Formatting

注意:这里描述的格式化操作展示了导致许多常见错误(例如未能正确地显示元组和字典)的各种怪癖。 使用较新的str.format()接口有助于避免这些错误,并且还提供了一种更加强大,灵活和可扩展的方法来格式化文本。

字符串对象有一个唯一的内置操作:%operator(modulo)。 这也称为字符串格式化或插值运算符。 给定格式%值(其中format是字符串),格式中的%转换规范将替换为零个或多个值元素。 效果类似于在C语言中使用sprintf()。

如果格式需要单个参数,那么值可以是单个非元组对象。 [5]否则,值必须是由格式字符串或单个映射对象(例如,字典)指定的项目数量的元组。

转换说明符包含两个或多个字符,并具有以下组件,它们必须按此顺序发生:

  1. '%'字符,它标记了说明符的开始。
  2. 映射键(可选),由带括号的字符序列组成(例如(somename))。
  3. 转换标志(可选),会影响某些转换类型的结果。
  4. 最小字段宽度(可选)。 如果指定为“*”(星号),则从值中的元组的下一个元素读取实际宽度,要转换的对象在最小字段宽度和可选精度之后。
  5. 精度(可选),作为'。'给出。 (点)后跟精度。 如果指定为“*”(星号),则从值的元组的下一个元素读取实际精度,并且转换的值在精度之后。
  6. 长度修饰符(可选)。
  7. 转换类型。

当正确的参数是字典(或其他映射类型)时,字符串中的格式必须包含一个括号映射键,该字符串插入紧跟在“%”字符之后的字典中。 映射键从映射中选择要格式化的值。 例如

>>> print('%(language)s has %(number)03d quote types.' %
...       {'language': "Python", "number": 2})
Python has 002 quote types.

在这种情况下,在格式中可能不会出现*说明符(因为它们需要顺序参数列表)。

转换标志字符为:

标识 含义
# 值转换将使用“备用形式”(以下定义)。
0 转换将被零填充为数值。
- 转换的值被左调整(如果两者都被给定,则覆盖'0'转换)。
空格 (空格)空格应留在由带符号的转换产生的正数(或空字符串)之前。
+ 符号字符('+'或' - ')将在转换之前(覆盖“空格”标志)。

长度修饰符(h,l或L)可以存在,但是被忽略,因为对于Python不是必要的。 %ld与%d相同。

转换类型有:

转换 含义 注释
d 有符号的十进制整数。  
i 有符号整数十进制。  
o 签名的八进制值 1
u 过时类型 - 它与'd'相同。 7
x 带符号的十六进制(小写)。 2
X 带符号的十六进制(大写)。 2
e 浮点指数格式(小写)。 3
E 浮点指数格式(大写)。 3
f 浮点十进制格式。 3
F 浮点十进制格式。 3
g 浮点格式。 如果指数小于-4或不小于精度,则使用小写指数格式,否则使用十进制格式。 4
G 浮点格式。 如果指数小于-4或不小于精度,则使用大写指数格式,否则使用十进制格式。 4
c 单个字符(接受整数或单个字符字符串)。  
r String(使用repr()转换任何Python对象)。 5
s String(使用str()转换任何Python对象)。 5
a String(使用ascii()转换任何Python对象)。 5
% 没有转换参数,在结果中产生一个'%'字符。  

注释:

1、如果结果的前导字符不是零,则替换形式使前导零('0')插入左侧填充和数字的格式化之间。

2、替代形式导致在左侧填充和数字格式之间插入前导'0x'或'0X'(取决于是否使用'x'或'X'格式),如果结果的前导字符 不是已经是零。

3、备用形式使结果始终包含小数点,即使后面没有数字。精度确定小数点后的位数,默认为6。

4、替代形式导致结果始终包含小数点,并且尾部零不会被删除,因为它们将是。精度确定小数点前后的有效数字个数,默认为6。

5、如果precision为N,则输出将截断为N个字符。

7、见PEP 237

由于Python字符串有明确的长度,%s的转换不假定' 0'是字符串的结尾。

在版本3.1中更改:对于绝对值超过1e50的数字,%f转化次数不会再被%g次转化替换。

3 >> printf-style Bytes Formatting

注意:这里描述的格式化操作展示了导致许多常见错误(例如未能正确地显示元组和字典)的各种怪癖。 如果正在打印的值可能是元组或字典,请将其包装在元组中。

字节对象(字节/字节)有一个独特的内置操作:%操作符(模)。 这也称为字节格式化或插值运算符。 给定格式%值(其中format是字节对象),格式中的%转换规范将替换为零个或多个值元素。 效果类似于在C语言中使用sprintf()。

如果格式需要单个参数,那么值可以是单个非元组对象。 否则,值必须是由字节对象或单个映射对象(例如字典)指定的项目数量的元组。

转换说明符包含两个或多个字符,并具有以下组件,它们必须按此顺序发生:

  1. '%'字符,它标记了说明符的开始。
  2. 映射键(可选),由带括号的字符序列组成(例如(somename))。
  3. 转换标志(可选),会影响某些转换类型的结果。
  4. 最小字段宽度(可选)。 如果指定为“*”(星号),则从值中的元组的下一个元素读取实际宽度,要转换的对象在最小字段宽度和可选精度之后。
  5. 精度(可选),作为'。'给出。 (点)后跟精度。 如果指定为“*”(星号),则从值的元组的下一个元素读取实际精度,并且转换的值在精度之后。
  6. 长度修饰符(可选)。
  7. 转换类型。

当正确的参数是字典(或其他映射类型)时,字节对象中的格式必须包含一个括号映射键,插入紧跟在“%”字符之后的字典中。 映射键从映射中选择要格式化的值。 例如:

>>> print(b'%(language)s has %(number)03d quote types.' %
...       {b'language': b"Python", b"number": 2})
b'Python has 002 quote types.'

在这种情况下,在格式中可能不会出现*说明符(因为它们需要顺序参数列表)。

转换标志字符为:

标识 含义
# 值转换将使用“备用形式”(以下定义)。
0 转换将被零填充为数值。
- 转换的值被左调整(如果两者都被给定,则覆盖'0'转换)。
空格 (空格)空格应留在由带符号的转换产生的正数(或空字符串)之前。
+ 符号字符('+'或' - ')将在转换之前(覆盖“空格”标志)。

长度修饰符(h,l或L)可以存在,但是被忽略,因为对于Python不是必要的。 %ld与%d相同。

转换类型有:

转换 含义 注释
d 有符号整数十进制。  
i 有符号整数十进制。  
o 签名的八进制值。 1
u 过时类型 - 它与'd'相同。 8
x 带符号的十六进制(小写)。 2
X 带符号的十六进制(大写)。 2
e 浮点指数格式(小写)。 3
E 浮点指数格式(大写)。 3
f 浮点十进制格式。 3
F 浮点十进制格式。 3
g 浮点格式。如果指数小于-4或不小于精度,则使用小写指数格式,否则使用十进制格式。 4
G 浮点格式。如果指数小于-4或不小于精度,则使用大写指数格式,否则使用十进制格式。 4
c 单字节(接受整数或单字节对象)。  
b Bytes(跟随缓冲区协议的任何对象或__bytes __()) 5
s 's'是'b'的别名,应该只用于Python2 / 3代码库。 6
a Bytes(使用repr(obj).encode('ascii','backslashreplace)转换任何Python对象)。 5
r r'是'a'的别名,应该只用于Python2 / 3代码库。 7
% 没有转换参数,在结果中产生一个'%'字符。  

1、如果结果的前导字符不是零,则替换形式使前导零('0')插入左侧填充和数字的格式化之间。

2、替代形式导致在左侧填充和数字格式之间插入前导'0x'或'0X'(取决于是否使用'x'或'X'格式),如果结果的前导字符不是已经是零。

3、备用形式使结果始终包含小数点,即使后面没有数字。精度确定小数点后的位数,默认为6。

4、替代形式导致结果始终包含小数点,并且尾部零不会被删除,因为它们将是。精度确定小数点前后的有效数字个数,默认为6。

5、如果precision为N,则输出将截断为N个字符。

6、b'%s'已弃用,但不会在3.x系列期间删除。

7、b'%r'已弃用,但不会在3.x系列期间删除。

8、见PEP 237

注意:此方法的字节数组版本不会运行 - 它总是产生一个新对象,即使没有进行任何更改。

参见PEP 461。

新版本3.5。

原文地址:https://www.cnblogs.com/yl153/p/6053097.html