如何格式化 Python 字符串?format,format_map 方法,Formatter 类介绍
本节内容不涉及 Python 旧式 printf 风格的字符串格式化,你可以查看Python 旧式 printf 风格字符串格式化使用说明一节来了解相关信息。
Python 字符串格式化中的替换字段
对于需要进行格式化的 Python 字符串,他们通常含有一些替换(格式)字段,替换字段由一个{}
及其包含的内容组成,并会被运算结果替换。
替换字段可能被 Pythonstr
类型的format
和format_map
方法,格式化字符串,或string
模块的Formatter
类使用,以用来引用方法的参数或当前可访问的变量等内容。
如何在格式化 Python 字符串时表示大括号自身?
在对 Python 字符串进行格式化时,{}
会被解释为替换字段,如果要在字符串中表示{
或}
自身,那么需要将其书写为{{
或}}
。
'{{}}'.format()
'{}'
Python str 类型的 format,format_map 方法
Pythonstr
类型的format
和format_map
方法,提供了格式化 Python 字符串的功能,只需要在字符串中书写替换字段,即可引用format
和format_map
方法提供的参数。
format(*args, **kwargs)
format_map(mapping)
- args 参数
可变参数
args
所包含的位置参数将被 Python 字符串中的替换字段引用。- kwargs 参数
可变参数
kwargs
所包含的关键字参数将被 Python 字符串中的替换字段引用。- mapping 参数
参数
mapping
通常是一个 Python 字典对象或通过__getitem__
方法提供值的对象,这些对象提供的值将被 Python 字符串中的替换字段引用。
在下面的示例中,我们定义了一个用于格式化的 Python 类Data
,该类将提供姓名和年龄信息,你需要在字符串中使用{name}
和{age}
来引用他们。
# 一个用于格式化的类
class Data:
def __getitem__(self, key):
# 提供姓名和年龄信息
if key == 'name':
return 'Jack'
elif key == 'age':
return 12
# 使用 {name} 和 {age} 进行引用
print('{name} 的年龄是 {age}'.format_map(Data()))
Jack 的年龄是 12
Python 格式化字符串
Python 格式化字符串是以f
或F
为前缀的字符串,此类字符串可以包含替换字段,并在其中书写 Python 表达式,表达式的计算结果将代替替换字段出现在字符串中。
a = 1
b = 2
F'{a} + {b} = {a + b}'
'1 + 2 = 3'
c = {'name': 'Jack', 'age': 12}
f'{len(c["name"]) > 3} {c["age"] > 12}'
'True False'
Python string 模块的 Formatter 类
Pythonstring
模块的Formatter
类,同样可用于格式化 Python 字符串,该类的实例方法format
和vformat
可实现与str
类型的format
和format_map
方法类似的效果。
formatter.format(format_string, /, *args, **kwargs)
- format_string 参数
参数
format_string
是需要进行格式化的 Python 字符串。- args 参数
可变参数
args
所包含的位置参数将被format_string
参数中的替换字段引用。- kwargs 参数
可变参数
kwargs
所包含的关键字参数将被format_string
参数中的替换字段引用。
formatter.vformat(format_string, args, kwargs)
- format_string 参数
参数
format_string
是需要进行格式化的 Python 字符串。- args 参数
参数
args
是一个 Python 序列对象,其包含的元素(项)将被 Python 字符串中的替换字段引用。- kwargs 参数
参数
kwargs
是一个 Python 映射对象,其包含的元素(项)将被 Python 字符串中的替换字段引用。
import string
f = string.Formatter()
f.format('{name} {0}', 12, name='Jack')
'Jack 12'
f.vformat('{name} {0}', (12,), {'name': 'Jack'})
'Jack 12'
在字符串中引用方法的参数
对于 Pythonstr
类型的format
和format_map
方法,以及string
模块的Formatter
对象的format
和vformat
方法,字符串中的替换字段{}
将按照出现顺序引用format
方法中的位置参数,第一个出现的{}
引用第一个位置参数,第二个出现的{}
引用第二个位置参数,以此类推。
'{}: "{}"'.format('Jack', 'HELLO')
'Jack: "HELLO"'
如果需要在 Pythonstr
类型的format
方法,以及string
模块的Formatter
对象的format
和vformat
方法中引用指定位置的位置参数,那么可以在{}
中填写位置参数的索引,0
表示引用第一个位置参数。
Python 字符串中的替换字段不能引用不存在于 format 方法的位置参数
对于 Python 字符串中的替换字段{}
,如果其包含的索引所对应的位置参数不存在,那么异常IndexError: Replacement index … out of range for positional args tuple
将被引发。
'{0}: "{1}"'.format('Jack', 'HELLO')
'Jack: "HELLO"'
'{1}: "{0}"'.format('Jack', 'HELLO')
'HELLO: "Jack"'
'{0}: "{1}, {2}"'.format('Jack', 'HELLO')
…
IndexError: Replacement index 2 out of range for positional args tuple
如果需要在 Pythonstr
类型的format
或format_map
方法,以及string
模块的Formatter
对象的format
和vformat
方法中引用关键字参数,那么可以在{}
中填写关键字参数的名称。
Python 字符串中的替换字段不能引用不存在于 format,format_map 方法的关键字参数
如果 Python 字符串中的替换字段{}
所引用的关键字参数,并不存在于format
或format_map
方法,那么异常KeyError: '…'
将被引发。
'{name}: "{word}"'.format(name='Jack', word='HELLO')
'Jack: "HELLO"'
'{name}: "{word}"'.format_map({'name': 'Jack', 'word': 'HELLO'})
'Jack: "HELLO"'
'{name}: "{word} {other}"'.format_map({'name': 'Jack', 'word': 'HELLO'})
…
KeyError: 'other'
在字符串中引用方法的参数的特性
对于 Pythonstr
类型的format
和format_map
方法,以及string
模块的Formatter
对象的format
和vformat
方法,在字符串的替换字段中书写.attribute
可以访问相关参数的特性(比如,变量,属性等),其中attribute
为特性的名称。而书写[key]
可以间接调用相关参数的__getitem__
方法,这意味着你可以在替换字段中访问 Python 列表或字典的值。需要指出,在[key]
中书写引号是不可行的,比如[age]
不能书写为["age"]
或['age']
。
'{0.real} {0.imag}'.format(12.3-4.56j)
'12.3 -4.56'
'{0[0]} {0[1]} {1[name]} {1[age]}'.format((1, 2), {'name': 'jack', 'age': 12})
'1 2 jack 12'
'{colors[0]} {colors[1]}'.format(colors=('RED', 'GREEN'))
'RED GREEN'
指定用于格式化 Python 字符串中的引用目标的函数
在正常情况下,Python 字符串中的替换字段所引用的目标对象的__format__
方法会被调用,该方法的返回值会代替替换字段。如果希望调用其他函数,那么需要在替换字段中书写!
,比如,!s
会调用 Python 的str
的构造器(构造函数)来格式化目标对象,!r
会调用 Python 的repr
函数,!a
会调用 Python 的ascii
函数。
Python 对象的 __format__ 方法可能返回其他方法的返回值
Python 对象的__format__
方法可能会直接或间接调用该对象的其他方法(比如__str__
),并返回该方法的返回值。
Python 的 ascii 函数与 repr 函数的区别
Python 的ascii
和repr
函数的返回值是类似的,只不过在ascii
函数的返回值中,非 ASCII 字符将被转换为其对应的编码值。
在下面的示例中,Python 类Data
定义了自己的方法__format__
,__str__
和__repr__
,他们将在不同的情况下被调用。
# 一个用于格式化的类
class Data:
def __format__(self, format_spec):
return '__format__'
def __str__(self):
return '__str__'
def __repr__(self):
return '<对象 "Data">'
# 对象的 __format__ 方法将被调用
print('{}'.format(Data()))
# str 的构造器将被调用
print('{!s}'.format(Data()))
# repr 函数将被调用
print('{!r}'.format(Data()))
# ascii 函数将被调用
print('{0!a}'.format(Data()))
__format__
__str__
<对象 "Data">
<\u5bf9\u8c61 "Data">
Python 字符串格式化中的格式规格
格式规格(Format Specification)被包含在 Python 字符串的替换字段中,用于定义如何展示替换字段所对应的值(比如,数字或字符串),其基本的格式如下。
[<alignment>][sign][z][#][0][width][group][<precision>][type]
- alignment 部分
alignment
部分用于设置对齐方式,具体请参考设置对齐方式一段。- sign 值
sign
用于设置数字符号的显示方式,具体请参考为数字设置符号显示方式一段。- z
z
表示将浮点数-0.
视为浮点数0.
,将复数-0j
或-0.j
视为复数(0+0j)
,将decimal.Decimal(-0.)
视为decimal.Decimal(0.)
。- # 值
#
表示为整数显示相关前缀,比如0b
(二进制),0o
(八进制),0x
或0X
(十六进制),或者强制为浮点数和复数显示小数点。- 0
0
表示自动添加字符0
,如果有剩余空间的话。- width 值
width
表示替换字段占用的最小空间(长度),如果忽略他,则替换字段的空间由其对应的值来决定。- group 值
group
为数字的分隔符,可以是下划线_
或逗号,
,具体请参考为数字设置分隔符一段。- precision 部分
precision
部分通常表示数字的精度,具体请参考为数字设置精度一段。- type 值
type
用于设置数字或字符串的具体呈现方式,具体请参考为数字和字符串设置具体呈现方式一段。
'{:}'.format(-0.)
'-0.0'
'{:z}'.format(-0.)
'0.0'
'{:07}'.format(-1.23)
'-001.23'
'{:07}'.format('abc')
'abc0000'
'{:#b}'.format(12345)
'0b11000000111001'
'{:#}'.format(1+1j)
'(1.+1.j)'
在格式化 Python 字符串时设置对齐方式
如果需要在格式化 Python 字符串时设置对齐方式,那么应该给出格式规格的alignment
部分,其格式如下。需要指出的是,对齐方式仅在可用空间足够时有效,比如,width
指定了足够的空间。
[fill]align
- fill 值
fill
是一个字符,用于填充替换字段的剩余空间,默认为空格。- align 值
align
表示对齐方式,如果设置为<
(大部分情况下的默认值),则采用左对齐,如果设置为>
(数字的默认值),则采用右对齐,如果设置为=
(仅对 Python 数字类型有效,但不包含 complex 类型),则在符号(比如,-
,+
)与数位之间填充fill
所表示的字符,如果设置为^
,则采用居中对齐(如果无法完成居中,则右边填充的字符会多于左边填充的字符)。
'{:<10}'.format(1.23)
'1.23 '
'{: >10}'.format(1.23)
' 1.23'
'{:-^10}'.format(1.23)
'---1.23---'
'{:-^11}'.format(1.23)
'---1.23----'
'{:0=10}'.format(-1.23)
'-000001.23'
'{:=3}'.format(-1.23)
'-1.23'
'{:0=10}'.format(-1.23j)
…
ValueError: Zero padding is not allowed in complex format specifier
Python 字符串格式化中的格式规格中的 0
对于格式规格的alignment
部分,如果fill
为0
,那么等同于使用格式规格中的0
。
'{:0>5}'.format(1)
'00001'
'{:05}'.format(1)
'00001'
在格式化 Python 字符串时为数字设置符号显示方式
如果需要在格式化 Python 字符串时为数字设置符号的显示方式,那么应该给出格式规格中的sign
。sign
仅对 Python 数字类型有效,他可以是以下几项之一,+
表示正数应显示正号+
,负数应显示负号-
。-
表示负数应显示负号-
,而正数不需要显示符号。
(空格)表示正数前应显示
(空格),负数应显示负号-
。
'{:+}'.format(1.23)
'+1.23'
'{:+}'.format(-1.23)
'-1.23'
'{:-}'.format(+1.23j)
'1.23j'
'{:-}'.format(-1.23j)
'(-0-1.23j)'
'{: }'.format(1.23)
' 1.23'
'{: }'.format(-1.23)
'-1.23'
在格式化 Python 字符串时为数字设置分隔符
如果需要在格式化 Python 字符串时为数字设置分隔符,那么应该给出格式规格中的group
,他可以是下划线_
或逗号,
。_
表示使用_
作为最终显示的十进制数字的整数部分的千位分隔符,或使用_
作为最终显示的其他进制数字的整数部分的四位分隔符(每四个数位插入一个分隔符)。,
表示使用,
作为最终显示的十进制数字的整数部分的千位分隔符。
'{:_}'.format(1234567.89)
'1_234_567.89'
'{:_X}'.format(123456789)
'75B_CD15'
'{:_b}'.format(123456789)
'111_0101_1011_1100_1101_0001_0101'
'{:_}'.format(123456789.12345j)
'123_456_789.12345j'
'{:,}'.format(-123456789.12345j)
'(-0-123,456,789.12345j)'
在格式化 Python 字符串时为数字设置精度
如果需要在格式化 Python 字符串时为数字设置精度,那么应该给出格式规格中的precision
部分,其格式如下。如果替换字段所对应的数字的精度超出了限制,那么数字将被舍入。
.prec
- prec 值
prec
为数字精度,当格式规格中的type
为f
,F
,e
或E
时,精度是指小数点后的位数(将自动补0
)。当格式规格中的type
为g
,G
或被忽略时,精度是指小数点前后的所有位数(不会自动补0
)。
'{:.5f}'.format(1)
'1.00000'
'{:.5f}'.format(1.23456789)
'1.23457'
'{:.5f}'.format(1.23j)
'0.00000+1.23000j'
'{:.5e}'.format(-0xABC123)
'-1.12561e+07'
'{:.5g}'.format(1.2)
'1.2'
'{:.5g}'.format(1234-123456j)
'1234-1.2346e+05j'
'{:.5}'.format(1234-123456j)
'(1234-1.2346e+05j)'
'{:.6}'.format(111111.)
'1.11111e+05'
Python 字符串格式化中的格式规格中的 precision 部分可以限制字符串长度
在 Python 字符串的格式化中,虽然格式规格中的precision
部分通常用于限制数字的精度,但他同样可以用于限制字符串的长度。
'{:.3}'.format('Hello')
'Hel'
在格式化 Python 字符串时为数字和字符串设置具体呈现方式
在格式化 Python 字符串的过程中,通过指定格式规格中的type
,你可以为替换字段对应的数字或字符串设置具体的呈现方式。
对于整数数字,type
拥有以下取值,b
表示将数字显示为二进制格式,o
表示将数字显示为八进制格式,d
(默认值)表示将数字显示为十进制格式,x
表示将数字显示为十六进制格式,其中字母为小写,X
同样表示将数字显示为十六进制格式,但字母为大写。n
与d
类似,但n
会根据当前区域设置来决定是否插入数字分隔符。c
表示将数字转换为对应的 Unicode 字符。
'{:b}'.format(123)
'1111011'
'{:#x}'.format(0xA1B1C1)
'0xa1b1c1'
'{:c}'.format(65)
'A'
对于浮点数,复数或类型为decimal.Decimal
的数字,type
拥有以下取值。需要指出,这些取值同样可用于整数,但在此之前整数(int
)会被转换为浮点数(float
)。
e
表示将数字显示为科学计数法,此时格式规格中的precision
表示小数点后的位数,如果未指定precision
,则精度默认为6
或尝试显示完整的小数部分(对于decimal.Decimal
)。E
与e
类似,但会采用大写字母。
f
表示将数字显示为定点数,此时格式规格中的precision
表示小数点后的位数,如果未指定precision
,则精度默认为6
或尝试显示完整的小数部分(对于decimal.Decimal
)。F
与f
类似,但会采用大写字母(比如,nan
显示为NAN
,inf
显示为INF
)。
g
表示根据格式规格中的precision
(精度为0
会被视为1
)和数字的值来选择是否使用科学计数法显示数字,数字末尾无意义的0
和小数点会被省略(除非使用#
),如果未指定precision
,则精度默认为6
或尝试显示完整的小数部分(对于decimal.Decimal
)。G
与g
类似,但会采用大写字母。
n
与d
类似,但n
会根据当前区域设置来决定是否插入数字分隔符。c
表示将数字转换为对应的 Unicode 字符。%
(不适用于复数)表示以百分比的形式显示数字,这相当于数字乘以100
并被添加了一个百分号%
。
如果没有为浮点数或复数指定type
,那么相当于使用了g
(但会尝试在没有给出精度时显示完整的数字,并尝试去掉复数的实数部分),只不过显示结果中的定点数的小数点后的精度至少为1
。如果没有为decimal.Decimal
类型的数字指定type
,那么相当于使用了g
或G
,具体选择由decimal
的上下文决定,你可以通过设置上下文的capitals
变量来完成此目标,设置为1
(默认值)将采用G
,设置为0
将采用g
,具体形式如下。
decimal.getcontext().capitals = capitals
- capitals 值
capitals
为1
(默认值)表示采用大写,为0
表示采用小写。
'{:.3e}'.format(1.2)
'1.200e+00'
'{:e}'.format(-12345678j)
'-0.000000e+00-1.234568e+07j'
'{:.3f}'.format(1.23j)
'0.000+1.230j'
'{:.3g}'.format(1.234j)
'0+1.23j'
'{:%}'.format(.23)
'23.000000%'
'{:}'.format(1.23456789)
'1.23456789'
'{:}'.format(-1.)
'-1.0'
'{:}'.format(1.234j)
'1.234j'
'{:}'.format(10000000000000000000.)
'1e+19'
对于字符串,type
可以是s
(默认值),通常情况下并不需要书写他,因为这对输出结果没有影响。
'{:s}'.format('Hello')
'Hello'
在格式化 Python 字符串时使用嵌套的替换字段
在格式化 Python 字符串时,你可以在一个替换字段中写入另一个替换字段,被写入的替换字段通常会作为格式规格的一部分,比如,作为格式规格中的width
或sign
。
'{0:{1}}'.format(1.23456, '10')
' 1.23456'
'{0:{1}}'.format(1.23456, '.5')
'1.2346'
'{0:{c}<{l}}'.format(1.23456, c='+', l=15)
'1.23456++++++++'
源码
src/zh/data_types/text_types/format·codebeatme/python·GitHub