摘要: In [1]: from env_helper import info; info() 页面更新时间: 2021-09-02 10:00:53 运行环境: Linux发行版本: Debian GNU/Linux 11 (bu...
from env_helper import info; info()
Python中字符串格式化¶
Python格式化字符串由四种方式可以选择:
- 一种是格式化表达式(Formatting Expression)
- 一种是格式化方法(Formatting Method)。
- 字符串字面值插值(f字符串)
- 使用类
Template
其中格式化表达式在全Python版本支持,而格式化方法在Python 2.6, Python 2.7和Python 3.1开始支持;Python 3.6+ 支持 f 字符串的方式。
字符串处理中拼接工作是经常会遇到的。字符串格式化的思想是使用占位符来代替要被替换的变量,这样在书写字符串时,可以直接看到结果的样式,从而方便书写与检查。
在每种方法中,都有控制格式的方式。这几种方法控制格式的方式类似,但又有一些差别。从实现的角度来讲,这几种方式都可以实现字符串格式化,但是效率上有一点差异。
但是该什么时候才在你的代码中使用模板字符串呢?在我看来,使用模板字符串的最佳的时机就是当你的程序需要处理由用户提供的输入内容时。模板字符串是最保险的选择,因为可以降低复杂性。
其他一些复杂的字符串格式化技巧的可能会给你的程序带来安全漏洞
Python字符串格式化经验法则
Python字符串格式化经验法则:如果你的格式化字符串是由用户提供的,那么就是用模板字符串(#4)避免安全问题。不然如果是Python 3.6+的话,就使用字符串插值/f-Strings,如果不是就使用“新式”字符串格式化(str.format)。
格式化表达式:使用 %
格式符¶
%
格式符使用 %
声明占位符的开始,并提供了一些格式控制的约定。%
格式符没法声明结束符,只能靠 Python 约定的方式来解析。在字符串定义结束后,使用 %
操作符向定义的字符串传递参数。
有两种方式,一种是无命名的,这时使用列表或元组传递参数,按相应的顺序:
'%s'%('hello')
'%s'%['hello']
第二种是有命名的,这时使用字符传递参数,字典的键与占位符的名称相对应。
'%(s)s, %(name)s' % {'s':'hello', 'name':'Tom'}
%[(name)][flags][width].[precision]typecode
(name)
可选,用于选择指定的keyflags
可选,可供选择的值有:+
右对齐;正数前加正好,负数前加负号;-
左对齐;正数前无符号,负数前加负号;空格
右对齐;正数前加空格,负数前加负号;0
右对齐;正数前无符号,负数前加负号;用0填充空白处
width
可选,占有宽度.precision
可选,小数点后保留的位数typecode
必选s
,获取传入对象的__str__
方法的返回值,并将其格式化到指定位置r
,获取传入对象的__repr__
方法的返回值,并将其格式化到指定位置c
,整数:将数字转换成其unicode对应的值,10进制范围为0 <= i <= 1114111
(py27则只支持0-255);字符:将字符添加到指定位置o
,将整数转换成 八 进制表示,并将其格式化到指定位置x
,将整数转换成十六进制表示,并将其格式化到指定位置d
,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置e
,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)E
,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)f
, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)F
,同上g
,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)G
,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)%
,当字符串中存在格式化标志时,需要用%%
表示一个百分号
注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式
接下来将举例部分参数的用法。
(name)
可选,用于选择指定的key
"%(name)s-----%(age)d" % {'name':'Kitty','age':20}
width
可选,占有宽度
name
占10位,+
,右对齐,age
占10位,-
,左对齐
"%(name)+10s————————%(age)-10d————————"%{'name':'Kitty','age':20}
.precision
可选,小数点后保留的位数
只保留两位小数
'--------%(p).2f'%{'p':1.23456}
'--------%(p)f'%{'p':1.23456}
typecode
必选 , 是指输入点位的类型。
c
,整数:将数字转换成其unicode对应的值,10进制范围为0 <= i <= 1114111
(py27则只支持0-255);字符:将字符添加到指定位置o
,将整数转换成 八 进制表示,并将其格式化到指定位置x
,将整数转换成十六进制表示,并将其格式化到指定位置
'***%c***%o***%x'%(65,15,15)
格式化方法:使用 format()
函数¶
由于 %
格式符没有结束符,所以在书写及使用的时候需要更多的工作,于是产生了 format()
函数来实现格式化的方法。在这种方式中,使用 {}
作为占位符的声明方式。
同样有两种方式,一种是无命名的,向 format()
函数传递相应的参数,来完成格式化:
'{}'.format('welcome')
命名的方式只需要在 {name}
中声明,这时传递参数的时候使用关键词参数:
'{}, Tome.'.format('welcome')
可以看出这种方式要更清晰一些。
数字格式的定义以 ':
' 号开始。碰到了':
'字符就知道要定义一个数字的显示格式了。格式的定义顺序为
[[fill]align][sign][#][0][width][,][.precision][type]
[[fill]align][sign][#][0][width][,][.precision][type]
fill
【可选】空白处填充的字符align
【可选】对齐方式(需配合width使用)<
,内容左对齐>
,内容右对齐(默认)=
,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。 即使:符号+填充物+数字^
,内容居中
sign
【可选】有无符号数字+
,正号加正,负号加负;-
,正号不变,负号加负;空格
,正号空格,负号加负;
#
【可选】对于二进制、八进制、十六进制,如果加上#
,会显示0b/0o/0x
,否则不显示width
【可选】格式化位所占宽度,
【可选】为数字添加分隔符,如:1,000,000.precision
【可选】小数位保留精度type
【可选】格式化类型- 传入“字符串类型”的参数
s
,格式化字符串类型数据空白
,未指定类型,则默认是None,同s
- 传入“整数类型”的参数
b
,将10进制整数自动转换成2进制表示然后格式化c
,将10进制整数自动转换为其对应的unicode字符d
,十进制整数o
,将10进制整数自动转换成8进制表示然后格式化;x
,将10进制整数自动转换成16进制表示然后格式化(小写x)X
,将10进制整数自动转换成16进制表示然后格式化(大写X)
- 传入“ 浮点型或小数类型 ”的参数
e
, 转换为科学计数法(小写e)表示,然后格式化;E
, 转换为科学计数法(大写E)表示,然后格式化;f
, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;F
, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;g
, 自动在e和f中切换G
, 自动在E和F中切换%
,显示百分比(默认显示小数点后6位)
- 传入“字符串类型”的参数
接下来将举例部分参数的用法。
width
【可选】格式化位所占宽度
格式化位所占宽度为20,内容居中显示
'---{:*^20s}----'.format('welcome')
格式化位所占宽度为20,内容左对齐
'---{:*<20s}----'.format('to')
[#]
【可选】对于二进制、八进制、十六进制,如果加上#
,会显示 0b/0o/0x
,否则不显示
b
,将10进制整数自动转换成2进制表示然后格式化c
,将10进制整数自动转换为其对应的unicode字符d
,十进制整数o
,将10进制整数自动转换成8进制表示然后格式化;x
,将10进制整数自动转换成16进制表示然后格式化(小写x)X
,将10进制整数自动转换成16进制表示然后格式化(大写X)
"numbers: {:b},{:o},{:d},{:x},{:X}, {:%},{:c}".format(15, 15,
15, 15, 15, 15.87623,65)
"numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%},{1:c}".format(15,
65)
.precision
【可选】小数位保留精度
'---{:,d}----'.format(10000000)
'---{:.2f}----'.format(1.2345)
使用 f 字符串进行格式化¶
f-string,亦称为格式化字符串常量(formatted string literals),是Python3.6新引入的一种字符串格式化方法,该方法源于PEP 498 – Literal String Interpolation,主要目的是使格式化字符串的操作更加简便。f-string 在形式上是以 f
或 F
修饰符引领的字符串(f'xxx'
或 F'xxx'
),以大括号 {}
标明被替换的字段;f-string 在本质上并不是字符串常量,而是一个在运行时运算求值的表达式。
f-string 是 Python3.6 之后版本添加的,称之为字面量格式化字符串,是新的格式化字符串的语法。
f-string 格式化字符串以 f
开头,后面跟着字符串,字符串中的表达式用大括号 {}
包起来,它会将变量或表达式计算后的值替换进去,实例如下:
替换变量
name='Herry'
f'Hello {name}'
使用表达式
f'{1+2}'
用了这种方式明显更简单了,不用再去判断使用 %s
,还是 %d
。
表达式求值与函数调用
f-string的大括号 {}
可以填入表达式或调用函数,Python会求出其结果并填入返回的字符串内:
f'Complex number {(2 + 2j) / (2 - 3j)}'
import math
f'The answer is {math.log(math.pi)}'
引号、大括号与反斜杠
f-string大括号内所用的引号不能和大括号外的引号定界符冲突,可根据情况灵活切换'
和"
:
f'I am {"Eric"}'
若 '
和 "
不足以满足要求,还可以使用 '''
和 """
:
f"""He said {"I'm Eric"}"""
大括号外的引号还可以使用 \
转义,但大括号内不能使用\
转义:
f'''He\'ll say {"I'm Eric"}'''
f-string大括号外如果需要显示大括号,则应输入连续两个大括号 {{
和 }}
:
f'5 {"{stars}"}'
f'{{5}} {"stars"}'
上面提到,f-string大括号内不能使用\
转义,事实上不仅如此,f-string大括号内根本就不允许出现 \
。如果确实需要 \
,则应首先将包含 \
的内容用一个变量表示,再在f-string大括号内填入变量名:
newline = ord('\n')
f'newline: {newline}'
多行f-string
f-string还可用于多行字符串:
name = 'Eric'
age = 27
f"Hello!" \
f"I'm {name}." \
f"I'm {age}."
"Hello!I'm Eric.I'm 27."
f"""Hello!
I'm {name}.
I'm {age}."""
自定义格式:对齐、宽度、符号、补零、精度、进制等
f-string采用 {content:format}
设置字符串格式,其中 content
是替换并填入字符串的内容,可以是变量、表达式或函数等,format 是格式描述符。采用默认格式时不必指定 {:format}
,如上面例子所示只写 {content}
即可。
关于格式描述符的详细语法及含义可查阅Python官方文档,这里按使用时的先后顺序简要介绍常用格式描述符的含义与作用:
对齐相关格式描述符
格式描述符 含义与作用
<
左对齐(字符串默认对齐方式)>
右对齐(数值默认对齐方式)^
居中
数字符号相关格式描述符
格式描述符 含义与作用
+
负数前加负号-
,正数前加正号+
-
负数前加负号-
,正数前不加任何符号(默认)空格
负数前加负号-
,正数前加一个空格
注:仅适用于数值类型。
数字显示方式相关格式描述符
格式描述符 含义与作用
#
切换数字显示方式
注1:仅适用于数值类型。
注2:
#
对不同数值类型的作用效果不同,详见下表:
数值类型 不加
#
(默认) 加#
区别- 二进制整数 '
1111011
' '0b1111011
' 开头是否显示0b
- 八进制整数 '
173
' '0o173
' 开头是否显示0o
- 十进制整数 '
123
' '123
' 无区别 - 十六进制整数(小写字母) '
7b
' '0x7b
' 开头是否显示0x
- 十六进制整数(大写字母) '
7B
' '0X7B
' 开头是否显示0X
- 二进制整数 '
宽度与精度相关格式描述符
格式描述符 含义与作用
width 整数
width 指定宽度0width 整数
width 指定宽度,开头的 0 指定高位用 0 补足宽度width.precision
整数 width 指定宽度,整数 precision 指定显示精度
a = 123.456
f'a is {a:011.3f}'
0width
不可用于复数类型和非数值类型,width.precision
不可用于整数类型。
f'a is {a:8.2e}'
width.precision
用于不同格式类型的浮点数、复数时的含义也不同:用于 f
、F
、e
、E
和 %
时 precision
指定的是小数点后的位数,用于 g
和 G
时 precision
指定的是有效数字位数(小数点前位数+小数点后位数)。
f'a is {a:8.2%}'
f'a is {a:8.2g}'
width.precision
除浮点数、复数外还可用于字符串,此时 precision
含义是只使用字符串中前 precision 位字符。
s = 'hello'
f's is {s:8s}'
f's is {s:8.3s}'
千位分隔符相关格式描述符
格式描述符 含义与作用
,
使用,
作为千位分隔符_
使用_
作为千位分隔符
注1:若不指定 ,
或 _
,则f-string不使用任何千位分隔符,此为默认设置。
注2:,
仅适用于浮点数、复数与十进制整数:对于浮点数和复数,,
只分隔小数点前的数位。
注3:_
适用于浮点数、复数与二、八、十、十六进制整数:对于浮点数和复数,_
只分隔小数点前的数位;对于二、八、十六进制整数,固定从低位到高位每隔四位插入一个 _
(十进制整数是每隔三位插入一个 _
)。
格式类型相关格式描述符
基本格式类型
格式描述符 含义与作用 适用变量类型
s
普通字符串格式 字符串b
二进制整数格式 整数c
字符格式,按unicode编码将整数转换为对应字符 整数d
十进制整数格式 整数o
八进制整数格式 整数x
十六进制整数格式(小写字母) 整数X
十六进制整数格式(大写字母) 整数e
科学计数格式,以e
表示×10^
浮点数、复数、整数(自动转换为浮点数)E
与e
等价,但以E
表示×10^
浮点数、复数、整数(自动转换为浮点数)f
定点数格式,默认精度(precision)是6 浮点数、复数、整数(自动转换为浮点数)F
与f
等价,但将 nan 和 inf 换成 NAN 和 INF 浮点数、复数、整数(自动转换为浮点数)g
通用格式,小数用f
,大数用e
浮点数、复数、整数(自动转换为浮点数)G
与G
等价,但小数用F
,大数用E
浮点数、复数、整数(自动转换为浮点数)%
百分比格式,数字自动乘上100后按f
格式排版,并加%
后缀 浮点数、整数(自动转换为浮点数)
居中,宽度10位,十六进制整数(大写字母),显示0X前缀
a = 1234
f'a is {a:^#10X}'
左对齐,宽度10位,显示正号+
,定点数格式,2位小数
b = 1234.5678
f'b is {b:<+10.2f}'
高位补零,宽度15位,十进制整数,使用,作为千分分割位
c = 12345678
f'c is {c:015,d}'
宽度30位,科学计数法,3位小数
d = 0.5 + 2.5j
f'd is {d:30.3e}'
对于 datetime
的变量,使用使用其独有的格式化符:
常用的特殊格式类型:标准库 datetime 给定的用于排版时间信息的格式类型,适用于 date、datetime 和 time 对象
%Y
年(完整数字,不补零)%m
月(数字,以 0 补足两位)%d
日(数字,以 0 补足两位)%a
星期几(缩写)
import datetime
e = datetime.datetime.today()
f'the time is {e:%Y-%m-%d (%a)}'
lambda表达式
f-string大括号内也可填入lambda表达式,但lambda表达式的 : 会被f-string误认为是表达式与格式描述符之间的分隔符,为避免歧义,需要将lambda表达式置于括号 ()
内:
f'result is {(lambda x: x ** 2 + 1) (2):<+7.2f}'
使用 Template 类进行字符串格式化¶
Python中Template是string中的一个类,可以将字符串的格式固定下来,重复利用。可以用于自动生成测试用例。Template 类同样是使用占位符这种基础的思想,不过是使用了面向对象的模式。
用法很简单,先生成一个模板实例,然后调用替换函数substitute()
将模板中的两个地方替换掉。替换的内容是通过字典对调用的,所以下面(lang='Python',howmany=3
)出现的顺序可以不用严格的和模板中的一样。
注意:在使用${howmany} ${lang}
时候,括号里的内容和括号要紧贴着,不然会报错。
from string import Template
s = Template("there are ${howmany} ${lang} Quotation symbols")
s.substitute(lang='Python',howmany=3)
如果变量定义的地方后面跟着空格,这种时候可以不用括号:
s = Template("there are $howmany $lang Quotation symbols")
s.substitute(lang='Python',howmany=3)
在使用 substitute()
函数的时候,对应的关键字和值都要给出,不然会报错。可以使用 safe_substitute()
以避免运行出错,但结果可能跟预期的不一样。
from string import Template
s = Template("there are ${howmany} ${lang} Quotation symbols")
s.safe_substitute(lang='Python')