Python 格式化字符串
1 简介
Python
目前有两种进行格式化字符串的方式:
- 使用
%
操作符进行格式化字符串 - 使用
str.format()
方法进行格式化字符串
官方推荐的方式是使用 str.format
方法。
官方文档链接:
2 使用 str.format()
2.1 格式化字符串语法
format
字符串包含由 {}
括起来的替换字段, 不包含在 {}
中的内容不做处理。
format
字符串可以通过 {{
和 }}
的方式来包含 {
和 }
.
替换字段语法:
替换字段 - 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" 格式规范说明符 - format_spec ::= <described in the next section>
注意事项:
参数名 - 可以为 整数 或 关键字. 整数为位置参数, 关键字为命名关键字参数。
如果整数类似于
{0}{1}{2}
, 则可以省略, 即:{}{}{}
等价于{0}{1}{2}
.如果参数存在属性, 可以通过
arg_name.attribute_name
的形式获取属性值。如果参数为可迭代对象, 可以通过
arg_name[integer|index_string]
的形式获取索引位置的元素。- 转换字段 - 由
!
开始,r
代表调用repr()
,s
代表调用str()
. - 格式规范说明符 - 由
:
开始。
示例:
"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' 的第一个元素 "Units destroyed: {players[key]}" # 关键字参数 'players' 'key' 键上的元素 "Harold's a clever {0!s}" # 首先在参数上调用 str() "Bring out the holy {name!r}" # 首先在参数上调用 repr()
2.2 格式说明符
format_spec
允许定义该替换字段的表现形式, 如左右对齐, 宽度等。
标准格式说明符的一般形式:
格式说明符格式 - 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" | "%"
填充字符 - 如果自定了有效的对齐值, 则可以指定填充字符。 默认为 空格.
对齐选项:
Option Meaning <
左对齐, 大多数对象的默认值 >
右对齐, 数字的默认值 =
强制将填充放置在符号(如果有)之后但位于数字之前, 仅适用于数字参数 ^
居中 示例:
>>> '{0:?<10}'.format(123456) '123456????' >>> '{0:?>10}'.format(123456) '????123456' >>> '{0:?=10}'.format(123456) '????123456' >>> '{0:?=10}'.format(-123456) '-???123456' >>> '{0:?^10}'.format(-123456) '?-123456??'
符号选项 - 符号选项只适用于数字参数。
符号选项:
Option Meaning +
显示正负数的符号 -
仅显示负数符号(默认) <SPC>
表示在正数前添加空格 示例:
>>> '{0:+}'.format(123456) '+123456' >>> '{0:+}'.format(-123456) '-123456' >>> '{0:-}'.format(123456) '123456' >>> '{0:-}'.format(-123456) '-123456' >>> '{0: }'.format(123456) ' 123456' >>> '{0: }'.format(-123456) '-123456'
# 选项 - 仅适用于数字参数, 同时仅适用于
2
,8
,16
进制的数字。 会在输出的数字前添加0b
,0o
,0x
前缀。示例:
>>> '{0:#}'.format(123456) '123456' >>> '{0:#o}'.format(123456) '0o361100' >>> '{0:#b}'.format(123456) '0b11110001001000000' >>> '{0:#x}'.format(123456) '0x1e240' >>> '{0:o}'.format(123456) '361100' >>> '{0:b}'.format(123456) '11110001001000000' >>> '{0:x}'.format(123456) '1e240'
, 选项 - 千位分隔符。
示例:
>>> '{0:,}'.format(123456) '123,456'
width 选项 - 指定最小字段宽度, 前面的对齐选项中已经用到了。
示例:
>>> '{0:8}'.format(123456) # 数字默认为 '>' ' 123456' >>> '{0:8}'.format('123456') # 字符串默认为 '<' '123456 '
0 选项 - 如果未给出明确的对齐方式, 可以在宽度字段前加上一个
0
字符。 这相当于填充字符0
, 对齐方式为=
.示例:
>>> '{0:08}'.format(-123456) '-0123456' >>> '{0:8}'.format(-123456) ' -123456'
precision 选项 - 对于由
f
或F
格式化的浮点数, 该选项指定小数点后的位数。 对于有g
或G
格式化的浮点数的小数点前后 一共 多少位。 对于非整数类型的参数, 该选项指定字段最大宽度。 精度不允许使用整数值.示例:
>>> '{0:.5f}'.format(123456) '123456.00000' >>> '{0:.5g}'.format(123456) '1.2346e+05' >>> '{0:.5}'.format('123456') '12345' >>> '{0:.5}'.format(123456) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Precision not allowed in integer format specifier
type 选项 - 该选项决定了数据应该如何呈现。
可用的字符串表示类型:
Type Meaning s
字符串格式, 字符串的默认类型, 可省略 None
同 s
可用的整数表示类型:
Type Meaning b
输出为 2 进制整数 c
输出为为相应的 unicode 字符 d
输出为 10 进制整数 o
输出为 8 进制整数 x
输出为 16 进制整数, 使用小写字母 X
输出为 16 进制整数, 使用大写字母 n
类似 d
, 会使用当前区域设置插入适当的数字分隔符None
同 d
可用的浮点数和小数值表示类型:
Type Meaning e
指数表示法, 使用字母 e
以科学记数法打印数字, 默认进度为 6E
类似 e
, 使用字母E
f
浮点数, 默认进度为 6 F
浮点数, 同 f
g
一般形式, 受 precision 选项影响 G
类似 g
, 当使用指数表示法时, 使用E
而不是e
n
和 g
相同, 会使用当前区域设置插入适当的数字分隔符%
百分数表示 None
同 g
3 使用 %
注: 这个方式不被推荐, 如果可以的话, 还是尽量使用 str.format()
这种方式的使用类似于 C
语言中的格式化字符串, 一般形式就是 format % value
.
格式:
- 字符
%
, 标志说明符的开始 - 映射键(可选), 有括号阔起来的字符序列指定, 如
%(key)
- 转换标志(可选), 影响某些转换类型的结果
最小字段宽度(可选)。 如果指定为
*
, 则实际宽度将从值的下一个元素中读取。并且要转换的值位于宽度之后。这在
str.format()
中可以由嵌套的替换字段实现, 如:>>> '{0:.{1}f}'.format(123456, 5) '123456.00000'
- 精度(可选)。 以
.
表示。 如果指定为*
, 则实际精度将从值的下一个元素中读取。并且要转换的值位于精度之后。 - 长度修饰符(可选)
- 转换类型
注: 如果值是一个字典, 那么字符串中的格式必须在 %
字符后面插入一个插入该字典的括号映射键.
如:
>>> print '%(language)s has %(number)03d quote types.' % \ ... {"language": "Python", "number": 2} Python has 002 quote types.
转换标志:
Flag | Meaning |
---|---|
# |
同 str.format() |
0 |
在数字前面填充 0 而不是默认的空格 |
- |
左对齐 |
<SPC> |
在正数前面显示空格 |
+ |
在正数前面显示 + |
转换类型:
Conversion | Meaning |
---|---|
d |
格式化整数 |
i |
格式化整数 |
o |
8 进制 |
u |
格式化无符号整型(已过时) |
x |
16 进制, 小写字母 |
X |
16 进制, 大写字母 |
e |
浮点指数格式, 小写字母 |
E |
浮点指数格式, 大写字母 |
f |
浮点数 |
F |
浮点数 |
g |
浮点数, 如果指数小于 -4 或小于精度, 则使用小写指数格式, 否则使用小数格式 |
G |
浮点数, 类似 g , 使用大写指数 |
c |
单个字符, 格式化字符及其 ASCII 码 |
r |
字符串, 使用 repr() 转换任何 Python 对象 |
s |
字符串, 使用 str() 转换任何 Python 对象 |
% |
% 字符 |
4 Update: 2018-04-18
这次更新是关于使用 str.format
的过程中包含 {}
的问题的。
以前遇到过的一个 Bug
, 其中有一串代码大概是这样的:
LOGIN_POST_DATA = r""" { "action": "login", "username": "", "password": "", "ac_id": "2", "user_ip": "{user_ip}", "nas_ip": "", "user_mac": "", "save_me": "1", "ajax": "1" } """.format(user_ip = socket.gethostbyname_ex(socket.gethostname())[-1][0]) # format keyerror
当时偷懒没有用字典, 直接使用了 Json
字符串。
结果就是一运行就出现 Keyerror
.
当时一直不明白是什么原因, 后来只能用 replace
来替代 format
.
今天, 这个 Bug
的原因搞清楚了 !
Json
啊! 有 {}
啊 !
改一下就好:
LOGIN_POST_DATA = r""" {{ "action": "login", "username": "", "password": "", "ac_id": "2", "user_ip": "{user_ip}", "nas_ip": "", "user_mac": "", "save_me": "1", "ajax": "1" }} """.format(user_ip = socket.gethostbyname_ex(socket.gethostname())[-1][0]) # format keyerror
细节问题很重要 !