2、格式化字符串

1.字符串格式化

python格式化字符串有三种方式:

  • python所有版本都能用的 %
  • 2.5版本以后添加的format()函数
  • 3.6后的f字符串

1.1 %格式化

参考:内置类型 — Python 3.13.0 文档

>>> print('%s has %d quote types.' % ('Python', 2))
Python has 2 quote types.
  • '%' 字符,用于标记转换符的起始。

  • 映射键(可选),由加圆括号的字符序列组成 (例如 (somename))。

    >>> 'name:%(name)s, age:%(age)s' % ({'name':'daming', 'age':'18'})
    'name:daming, age:18'
    #在此情况下格式中不能出现 * 标记符(因其需要一个序列类的参数列表)。
    
  • 转换旗标(可选),用于影响某些转换类型的结果。

旗标 含意
'#' 值的转换将使用“替代形式”。 '%#x' % 17
'0' 转换将为数字值填充零字符。'%09d' % 5
'-' 转换值将靠左对齐(如果同时给出 '0' 转换,则会覆盖后者)。'%-9d' % 5
' ' (空格) 符号位转换产生的正数(或空字符串)前将留出一个空格。'% d' % 5
'+' 符号字符 ('+''-') 将显示于转换结果的开头(会覆盖 "空格" 旗标)。'%+d' % 5
  • 最小字段宽度(可选)。 如果指定为 '*' (星号),则实际宽度会从 values 元组的下一元素中读取,要转换的对象则为最小字段宽度和可选的精度之后的元素。

  • 精度(可选),以在 '.' (点号) 之后加精度值的形式给出。 如果指定为 '*' (星号),则实际精度会从 values 元组的下一元素中读取,要转换的对象则为精度之后的元素。

    >>> '%*.*f   %*s'%(20,6,5,   10,'a')
    '            5.000000            a'
    
  • 长度修饰符(可选)。

    >>> 'ss:%10s' % 6
    'ss:         6'
    
  • 转换类型。如上述的s,用与将值装换成字符类型

格式化的类型:

转换符 含意 备注
'd' 有符号十进制整数。
'i' 有符号十进制整数。
'o' 有符号八进制数。 (1)
'u' 过时类型 -- 等价于 'd' (6)
'x' 有符号十六进制数(小写)。 (2)
'X' 有符号十六进制数(大写)。 (2)
'e' 浮点指数格式(小写)。 (3)
'E' 浮点指数格式(大写)。 (3)
'f' 浮点十进制格式。 (3)
'F' 浮点十进制格式。 (3)
'g' 浮点格式。 如果指数小于 -4 或不小于精度则使用小写指数格式,否则使用十进制格式。 (4)
'G' 浮点格式。 如果指数小于 -4 或不小于精度则使用大写指数格式,否则使用十进制格式。 (4)
'c' 单个字符(接受整数或单个字符的字符串)。
'r' 字符串(使用 repr() 转换任何 Python 对象)。 (5)
's' 字符串(使用 str() 转换任何 Python 对象)。 (5)
'a' 字符串(使用 ascii() 转换任何 Python 对象)。 (5)
'%' 不转换参数,在结果中输出一个 '%' 字符。

注释:

  1. 此替代形式会在第一个数码之前插入标示八进制数的前缀 ('0o')。

  2. 此替代形式会在第一个数码之前插入 '0x''0X' 前缀(取决于是使用 'x' 还是 'X' 格式)。

  3. 此替代形式总是会在结果中包含一个小数点,即使其后并没有数码。

    小数点后的数码位数由精度决定,默认为 6。

  4. 此替代形式总是会在结果中包含一个小数点,末尾各位的零不会如其他情况下那样被移除。

    小数点前后的有效数码位数由精度决定,默认为 6。

  5. 如果精度为 N,输出将截短为 N 个字符。

  6. 参见 PEP 237

>>> '%6.2i' % -6
'   -06'
>>> '%6.2d' % -6
'   -06'
>>>

>>> '%o' % 9
'11'
>>> '%#o' % 9
'0o11'
>>>

>>> '%x' % 17
'11'
>>> '%X' % 17
'11'
>>> '%#x' % 17
'0x11'
>>> '%#X' % 17
'0X11'
>>>

>>> '%.e' % 1000000000000000000000000000000000
'1e+33'
>>> '%.2e' % 1000000000000000000000000000000000
'1.00e+33'
>>> '%.E' % 1000000000000000000000000000000000
'1E+33'
>>> '%#.E' % 1000000000000000000000000000000000
'1.E+33'

>>> '%.f' % 5
'5'
>>> '%.F' % 5
'5'
>>> '%#.F' % 5
'5.'
>>> '%#.f' % 5
'5.'

>>> '%.5g' % 0.0001
'0.0001'
>>> '%.5g' % 0.000001
'1e-06'
>>> '%.5G' % 0.0001
'0.0001'
>>> '%.5G' % 0.000001
'1E-06'
>>> '%#.5G' % 0.0001
'0.00010000'
>>> '%#.5G' % 0.000001
'1.0000E-06'
>>> '%#.G' % 1
'1.'

1.2 format()函数

string --- 常见的字符串操作 — Python 3.13.0 文档

在大多数情况下,旧的语法和新语法可以转换的

'%03.2f' % 5 等于'{:03.2f}'.format(5)

格式字符串包含有以花括号 {} 括起来的“替换字段”。 不在花括号之内的内容被视为字面文本,会不加修改地复制到输出中。 如果你需要在字面文本中包含花括号字符,可以通过重复来转义: {{ and }}

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

"First, thou shalt count to {0}"  # 引用第一个位置参数
"Bring me a {}"                   # 隐式引用第一个位置参数
"From {} to {}"                   # 等同于 "From {0} to {1}"
"My quest is {name}"              # 引用关键字参数 'name'
"Weight in tons {0.weight}"       # 第一个位置参数的 'weight' 属性
"Units destroyed: {players[0]}"   # 关键字参数 'players' 的第一个元素。

目前支持的转换旗标有三种: '!s' 会对值调用 str()'!r' 调用 repr()'!a' 则调用 ascii()

"Harold's a clever {0!s}"        # 先在参数上调用 str()
"Bring out the holy {name!r}"    # 先在参数上调用 repr()
"More {!a}"                      # 先在参数上调用 ascii()

格式规格迷你语言

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

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

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

选项 含意
'<' 强制字段在可用空间内左对齐(这是大多数对象的默认值)。
'>' 强制字段在可用空间内右对齐(这是数字的默认值)。
'=' 强制在符号(如果有)之后数码之前放置填充。 这被用于以 '+000000120' 形式打印字段。 这个对齐选项仅对数字类型有效。 这是当 '0' 紧接在字段宽度之前时的默认选项。
'^' 强制字段在可用空间内居中。

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

选项 含意
"+" 表示标志应该用于正数和负数。
"-" 表示标志应仅用于负数(这是默认行为)。
" " 表示应在正数上使用前导空格,在负数上使用减号。

在 3.11 版本发生变更: ‘z’选项将负零浮点值在舍入到格式精度后强制转换为正零。此选项仅对浮点表示类型有效。

在 3.1 版本发生变更:',' 选项表示使用逗号作为千位分隔符。 对于感应区域设置的分隔符,请改用 'n' 整数表示类型。

>>> '{:,d}'.format(1000000000)
'1,000,000,000'

在 3.6 版本发生变更: '_' 选项表示对浮点表示类型和整数表示类型 'd' 使用下划线作为千位分隔符。 对于整数表示类型 'b', 'o', 'x''X',将为每 4 个数位插入一个下划线。 对于其他表示类型指定此选项则将导致错误。

>>> '{:_d}'.format(1000000000)
'1_000_000_000'
>>> '{:_x}'.format(100000000000000)
'5af3_107a_4000'

width 是一个定义最小总字段宽度的十进制整数,包括任何前缀、分隔符和其他格式化字符。 如果未指定,则字段宽度将由内容确定。

当未显式给出对齐方式时,在 width 字段前加一个零 ('0') 字段将为数字类型启用感知正负号的零填充。 这相当于设置 fill 字符为 '0'alignment 类型为 '='

在 3.10 版本发生变更:width 字段之前添加 '0' 不会再影响字符串的默认对齐。

precision 是一个十进制整数,表示浮点数的精度(小数点后显示多少个数位),或者字符串的最大长度

可用的字符串表示类型:

类型 含意
's' 字符串格式。这是字符串的默认类型,可以省略。
None 's' 一样。
>>> '{}'.format(5)
'5'
>>> '{!s}'.format(5)
'5'
>>> '{:s}'.format('a')
'a'
格式规格迷你语言与%对比
缺少:
'i' 有符号十进制整数。
'u' 过时类型 -- 等价于 'd'
新增:
'n' 数字。 这与 'g' 相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。
'%' 百分比。 将数字乘以 100 并显示为定点 ('f') 格式,后面带一个百分号。
None 总体效果是将 str() 的输出匹配为其他格式化因子所调整出的样子。

按位置访问参数:

>>> '{0}, {1}, {2}'.format('a', 'b', 'c')
'a, b, c'
>>> '{}, {}, {}'.format('a', 'b', 'c')  # 3.1+ only,等于示例1
'a, b, c'
>>> '{2}, {1}, {0}'.format('a', 'b', 'c')
'c, b, a'
>>> '{2}, {1}, {0}'.format(*'abc')      # 解包参数序列
'c, b, a'
>>> '{0}{1}{0}'.format('abra', 'cad')   # 参数的索引可重复使用
'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')  # 使用 '*' 作为填充字符
'***********centered***********'

替代 %+f, %-f% f 以及指定正负号:

>>> '{:+f}; {:+f}'.format(3.14, -3.14)  # 总是显示
'+3.140000; -3.140000'
>>> '{: f}; {: f}'.format(3.14, -3.14)  # 对正数显示一个空格
' 3.140000; -3.140000'
>>> '{:-f}; {:-f}'.format(3.14, -3.14)  # 只显示负号 -- 等同于 '{:f}; {:f}'
'3.140000; -3.140000'

替代 %x%o 以及转换基于不同进位制的值:

>>> # 格式也支持二进制数
>>> "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)  # _ = 'C0A80001'
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

1.3 f 字符串

2. 词法分析 — Python 3.13.0 文档

格式字符串字面值 或称 f-string 是标注了 'f''F' 前缀的字符串字面值。这种字符串可包含替换字段,即以 {} 标注的表达式。其他字符串字面值只是常量,格式字符串字面值则是可在运行时求值的表达式。

a = 'daming'
f"xxx{a[=]["!" ["s" | "r" | "a"]][":" format_spec}"

双花括号 '{{''}}' 被替换为单花括号

在 3.7 版本发生变更: Python 3.7 以前, 因为实现的问题,不允许在格式字符串字面值表达式中使用 await 表达式与包含 async for 子句的推导式。

在 3.12 版本发生变更: 在 Python 3.12 之前,不允许在 f-字符串的替换字段中使用注释。

版本新增3.8: 等号 '='

表达式里含等号 '=' 时,输出内容包括表达式文本、'=' 、求值结果。输出内容可以保留表达式中左花括号 '{' 后,及 '=' 后的空格。没有指定格式时,'=' 默认调用表达式的 repr()。指定了格式时,默认调用表达式的 str(),除非声明了转换字段 '!r'

>>> a = 3 + 6
>>> f'{a = }'
'a = 9'

格式字符串字面值示例如下:

>>> name = "Fred"
>>> f"He said his name is {name!r}."
"He said his name is 'Fred'."
>>> f"He said his name is {repr(name)}."  # repr() 等价于 !r
"He said his name is 'Fred'."
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}"  # 嵌套的字段
'result:      12.35'
>>> today = datetime(year=2017, month=1, day=27)
>>> f"{today:%B %d, %Y}"  # 使用日期格式说明符
'January 27, 2017'
>>> f"{today=:%B %d, %Y}" # 使用日期格式说明符和调试
'today=January 27, 2017'
>>> number = 1024
>>> f"{number:#0x}"  # 使用整数格式说明符
'0x400'
>>> foo = "bar"
>>> f"{ foo = }" # 保留空格
" foo = 'bar'"
>>> line = "The mill's closed"
>>> f"{line = }"
'line = "The mill\'s closed"'
>>> f"{line = :20}"
"line = The mill's closed   "
>>> f"{line = !r:20}"
'line = "The mill\'s closed" '

允许在替换字段中重用外层 f-字符串的引号类型:

>>> a = dict(x=2)
>>> f"abc {a["x"]} def"
'abc 2 def'

在 3.12 版本发生变更: 在 Python 3.12 之前不允许在替换字段中重用与外层 f-字符串相同的引号类型。

替换字段中也允许使用反斜杠并会以与在其他场景下相同的方式求值:

>>> a = ["a", "b", "c"]
>>> print(f"List a contains:\n{"\n".join(a)}")
List a contains:
a
b
c

在 3.12 版本发生变更: 在 Python 3.12 之前,f-字符串的替换字段内不允许使用反斜杠。

即便未包含表达式,格式字符串字面值也不能用作文档字符串。

>>> def foo():
...     f"Not a docstring"
...
>>> foo.__doc__ is None
True
posted on 2024-10-18 19:26  莫名丨其妙  阅读(31)  评论(0编辑  收藏  举报