目录
1. 术语说明
2. 简单字段名
2.1 简单字段名的说明
2.2 省略字段名
2.3 数字形式的简单字段名
2.4 变量名形式的简单字段名
2.5 简单字段名的混合使用
2.6 使用元组和字典传参
3. 复合字段名
3.1 复合字段名的说明
3.2 . 点号的使用
3.3 [] 方括号的使用
4. 转换字段
5. 格式说明符
5.1 标准格式说明符的格式
5.2 填充与对齐方式
5.3 正负号
5.4 # 号
5.5 最小宽度
5.6 分组选项
5.7 精度
5.8 类型码
5.8.1 字符串类型
6. 补充说明
参考资料
1. 术语说明
str.format() 方法通过字符串中的花括号 {} 来识别替换字段 replacement field,从而完成字符串的格式化。
替换字段 由字段名 field name 和转换字段 conversion field 以及格式说明符 format specifier 组成,即一般形式为 {字段名!转换字段:格式说明符}。
字段名分为简单字段名 simple field name 和复合字段名 compound field name。
而转换字段和格式说明符都是可选的。
2. 简单字段名
2.1 简单字段名的说明
简单字段名有三种写法:
省略不写 {}
数字 {十进制非负整数}
变量名 {合法的Python标识符}
2.2 省略字段名
花括号内省略字段名,传递位置参数。
替换字段形式: {}
注意:花括号个数可以少于位置参数的个数,反之不然。
# 省略字段名传递位置参数 print(\'我叫{},今年{}岁。\'.format(\'小明\', 18)) \"\"\" 我叫小明,今年18岁。 \"\"\" # 花括号个数可以少于位置参数的个数 print(\'我爱吃{}和{}。\'.format(\'香蕉\', \'苹果\', \'大鸭梨\')) \"\"\" 我爱吃香蕉和苹果。 \"\"\" # 花括号个数多于位置参数的个数则会报错 # print(\'我还吃{}和{}。\'.format(\'西红柿\')) \"\"\" IndexError: tuple index out of range \"\"\"
2.3 数字形式的简单字段名
可以通过数字形式的简单字段名传递位置参数。
数字必须是大于等于 0 的整数。
带数字的替换字段可以重复使用。
数字形式的简单字段名相当于把 format 中的所有位置参数整体当作一个元组,通过字段名中的数字进行取值。
即 {0} 等价于 tuple[0],所以花括号内的数字不能越界。
# 通过数字形式的简单字段名传递位置参数 print(\'身高{0},家住{1}。\'.format(1.8, \'铜锣湾\')) \"\"\" 身高1.8,家住铜锣湾 \"\"\" # 数字形式的简单字段名可以重复使用。 print(\'我爱{0}。\\n她今年{1}。\\n{0}也爱我。\'.format(\'阿香\', 17)) \"\"\" 我爱阿香。 她今年17。 阿香也爱我。 \"\"\" # 体会把所有位置参数整体当成元组来取值 print(\'阿香爱吃{1}、{3}和{0}。\'.format( \'榴莲\', \'臭豆腐\', \'皮蛋\', \'鲱鱼罐头\', \'螺狮粉\')) \"\"\" 阿香爱吃臭豆腐、鲱鱼罐头和榴莲。 \"\"\" # 尝试一下越界错误 # print(\'{1}\'.format(\'错误用法\')) \"\"\" IndexError: tuple index out of range \"\"\"
2.4 变量名形式的简单字段名
使用变量名形式的简单字段名传递关键字参数。
关键字参数的位置可以随意调换。
# 使用变量名形式的简单字段名传递关键字参数 print(\'我大哥是{name},今年{age}岁。\'.format(name=\'阿飞\', age=20)) \"\"\" 我大哥是阿飞,今年20岁。 \"\"\" # 关键字参数的顺序可以随意调换 print(\'我大哥是{name},今年{age}岁。\'.format(age=20, name=\'阿飞\')) \"\"\" 我大哥是阿飞,今年20岁。 \"\"\"
2.5 简单字段名的混合使用
混合使用数字形式和变量名形式的字段名,可以同时传递位置参数和关键字参数。
关键字参数必须位于位置参数之后。
混合使用时可以省略数字。
省略字段名 {} 不能和数字形式的字段名 {非负整数} 同时使用。
# 混合使用数字形式和变量名形式的字段名 # 可以同时传递位置参数和关键字参数 print(\'这是一个关于{0}、{1}和{girl}的故事。\'.format( \'小明\', \'阿飞\', girl=\'阿香\')) \"\"\" 这是一个关于小明、阿飞和阿香的故事。 \"\"\" # 但是关键字参数必须位于位置参数之后 # print(\'这是一个关于{0}、{1}和{girl}的故事。\'.format( # \'小明\', girl=\'阿香\' , \'阿飞\')) \"\"\" SyntaxError: positional argument follows keyword argument \"\"\" # 数字也可以省略 print(\'这是一个关于{}、{}和{girl}的故事。\'.format( \'小明\', \'阿飞\', girl=\'阿香\')) # 但是省略字段名不能和数字形式的字段名同时出现 # print(\'这是一个关于{}、{1}和{girl}的故事。\'.format( # \'小明\', \'阿飞\', girl=\'阿香\')) \"\"\" ValueError: cannot switch from automatic field numbering to manual field specification \"\"\"
2.6 使用元组和字典传参
str.format() 方法还可以使用 *元组 和 **字典 的形式传参,两者可以混合使用。
位置参数、关键字参数、*元组 和 **字典 也可以同时使用,但是要注意,位置参数要在关键字参数前面,*元组 要在 **字典 前面。
# 使用元组传参 infos = \'钢铁侠\', 66, \'小辣椒\' print(\'我是{},身价{}亿。\'.format(*infos)) \"\"\" 我是钢铁侠,身家66亿。 \"\"\" print(\'我是{2},身价{1}亿。\'.format(*infos)) \"\"\" 我是小辣椒,身家66亿。 \"\"\" # 使用字典传参 venom = {\'name\': \'毒液\', \'weakness\': \'火\'} print(\'我是{name},我怕{weakness}。\'.format(**venom)) \"\"\" 我是毒液,我怕火。 \"\"\" # 同时使用元组和字典传参 hulk = \'绿巨人\', \'拳头\' captain = {\'name\': \'美国队长\', \'weapon\': \'盾\'} print(\'我是{}, 我怕{weapon}。\'.format(*hulk, **captain)) print(\'我是{name}, 我怕{1}。\'.format(*hulk, **captain)) \"\"\" 我是绿巨人, 我怕盾。 我是美国队长, 我怕拳头。 \"\"\" # 同时使用位置参数、元组、关键字参数、字典传参 # 注意: # 位置参数要在关键字参数前面 # *元组要在**字典前面 tup = \'鹰眼\', dic = {\'weapon\': \'箭\'} text = \'我是{1},我怕{weakness}。我是{0},我用{weapon}。\' text = text.format( *tup, \'黑寡妇\', weakness=\'男人\', **dic) print(text) \"\"\" 我是黑寡妇,我怕男人。我是鹰眼,我用箭。 \"\"\"
3. 复合字段名
3.1 复合字段名的说明
同时使用了数字和变量名两种形式的字段名就是复合字段名。
复合字段名支持两种操作符:
[] 方括号
. 点号
3.2 . 点号的使用
传递位置参数
替换字段形式:{数字.属性名}
只有一个替换字段的时候可以省略数字
# 复合字段名中使用点号传递对象属性 class Person: def __init__(self, name, addr): self.name = name self.addr = addr p = Person(\'辣妹子\', \'重庆\') # 点号用法:传递位置参数 print(\'我是{0.name},家在{0.addr}。\'.format(p)) \"\"\" 我是辣妹子,家在重庆。 \"\"\" # 当只有一个替换字段的时候可以省略数字 print(\'{.name}辣!\'.format(p)) \"\"\" 辣妹子辣! \"\"\" # 试试传递文件对象的属性 f = open(\'out.txt\', \'w\') print(\'文件名为:{.name}\'.format(f)) f.close() \"\"\" 文件名为:out.txt \"\"\"
传递关键字参数
替换字段形式:{关键字参数名.属性名}
# 点号用法:传递关键字参数 print(\'我是{girl.name},家在{girl.addr}。\'.format(girl=p)) # 和上一句等价 print(\'我是{p.name},家在{p.addr}。\'.format(p=p)) \"\"\" 我是辣妹子,家在重庆。 我是辣妹子,家在重庆。 \"\"\"
3.3 [] 方括号的使用
传递位置参数
用列表传递位置参数
用元组传递位置参数
用字典传递位置参数
# 方括号用法:用列表传递位置参数 infos = [\'阿星\', 9527] food = [\'霸王花\', \'爆米花\'] print(\'我叫{0[0]},警号{0[1]},爱吃{1[0]}。\'.format( infos, food)) \"\"\" 我叫阿星,警号9527,爱吃霸王花。 \"\"\" # 方括号用法:用元组传递位置参数 food = (\'僵尸\', \'脑子\') print(\'我叫{0[0]},年龄{1},爱吃{0[1]}。\'.format( food, 66)) \"\"\" 我叫僵尸,年龄66,爱吃脑子。 \"\"\" # 方括号用法:用字典传递位置参数 dic = dict(name=\'阿星\', pid=9527) print(\'我是{[name]}!\'.format( dic)) # 多个替换字段,不能省略数字 print(\'我是{0[name]},警号{0[pid]}。\'.format( dic)) \"\"\" 我是阿星! 我是阿星,警号9527。 \"\"\"
传递关键字参数
用列表传递关键字参数
用元组传递关键字参数
用字典传递关键字参数
# 方括号用法:传递关键字参数 names = [\'皮卡丘\'] dic = {\'name\': \'妙蛙花\'} skills = (\'十万伏特\', \'飞叶快刀\') text = \'我是{names[0]},我会{skills[0]}。我是{dic[name]},我会{skills[1]}。\' text = text.format(names=names, skills=skills, dic=dic) print(text) \"\"\" 我是皮卡丘,我会十万伏特。我是妙蛙花,我会飞叶快刀。 \"\"\"
4. 转换字段
转换字段 conversion field 的取值有三种,前面要加 !:
s:传递参数之前先对参数调用 str()
r:传递参数之前先对参数调用 repr()
a:传递参数之前先对参数调用 ascii()
ascii() 函数类似 repr() 函数,返回一个可以表示对象的字符串。
但是对于非 ASCII 字符,使用 \\x,\\u 或者 \\U 转义。
# 转换字段 print(\'I am {!s}!\'.format(\'Bruce Lee 李小龙\')) print(\'I am {!r}!\'.format(\'Bruce Lee 李小龙\')) print(\'I am {!a}!\'.format(\'Bruce Lee 李小龙\')) \"\"\" I am Bruce Lee 李小龙! I am \'Bruce Lee 李小龙\'! I am \'Bruce Lee \\u674e\\u5c0f\\u9f99\'! \"\"\"
5. 格式说明符
在替换字段中,格式说明符前面有一个冒号 : :
{字段名!转换字段:格式说明符}
其中格式说明符本身可以是一个字段名,比如:
print(\'{0:{1}}\'.format(3.14159, \'.4f\')) \"\"\" 3.1416 \"\"\"
5.1 标准格式说明符的格式
如果不通过重写 __format__ 方法来进行自定义的话,标准格式说明符的形式如下。其中方括号是可选的。
[[fill]align][sign][#][0][width][grouping_option][.precision][type]
中文形式可以写作:
[[填充]对齐方式][正负号][#][0][宽度][分组选项][.精度][类型码]
5.2 填充与对齐方式
填充:
只能是一个字符
不指定默认用空格填充
如果指定填充字符,则必须要同时指定对齐方式
对齐方式的取值:
<:左对齐
>:右对齐
^:居中
=:在正负号(如果有的话)和数字之间填充,该对齐选项仅对数字类型有效。它可以输出类似 +0000120 这样的字符串。
注意:
如果不给定最小宽度 width,对齐方式毫无意义。
5.3 正负号
正负号选项仅对数字类型生效
取值有三种:
+ 正数前面添加正号,负数前面添加负号
– 仅在负数前面添加负号(默认行为)
空格:正数前面需要添加一个空格,以便与负数对齐
# 正负号 print(\'{:哈=+8.2f}\'.format(3.14159)) print(\'{:哈=+8.2f}\'.format(-3.14159)) print(\'{:哈=+8.2f}\'.format(0)) print(\'{:哈=+8.2f}\'.format(-0)) \"\"\" +哈哈哈3.14 -哈哈哈3.14 +哈哈哈0.00 +哈哈哈0.00 \"\"\"
5.4 # 号
# 号:
给u二进制数加上 0b 前缀
给八进制数加上 0o 前缀
给十六进制数加上 0x 前缀
5.5 最小宽度
最小宽度 width:
如果不指定,最小字段宽度由内容决定,与内容相等
如果最小宽度前面有一个前导 0,意味着用 0 填充
这等价于指定了 0= 的填充和对齐方式
5.6 分组选项
分组选项 grouping_option 的取值有两种:
逗号 ,:使用逗号对数字以千为单位进行分隔。n 类型的数字可以使用本地化的分隔符。
n类型在本机无法使用分组选项 ,
原因可能是中文没有数字分隔符
# n 类型使用本地化的分组选项 , # 此项报错,我怀疑是因为中文没有数字的分隔符 # print(\'数字:{0:,n}\'.format(6666)) \"\"\" ValueError: Cannot specify \',\' with \'n\'. \"\"\" # 使用 d 类型确实是可以的 print(\'数字:{0:,d}\'.format(6666)) \"\"\" 数字:6,666 \"\"\"
下划线 _:使用下划线对浮点数和 d 类型的整数以千为单位进行分隔。对于 b、o、x 和 X 类型,每四位插入一个下划线,其他类型都会报错。
# 分组选项 _ 作用于 b 类型 print(\'数字:{0:_b}\'.format(0b100111011)) \"\"\" 数字:1_0011_1011 \"\"\" # 分组选项 _ 作用于 o 类型 print(\'数字:{0:_o}\'.format(0o426754316)) \"\"\" 数字:4_2675_4316 \"\"\" # 分组选项 _ 作用于 x 类型 print(\'数字:{0:_x}\'.format(0x2a846e98d)) \"\"\" 数字:2_a846_e98d \"\"\" # 分组选项 _ 作用于 X 类型 print(\'数字:{0:_X}\'.format(0X2a846e98d)) \"\"\" 数字:2_A846_E98D \"\"\" # 分组选项 _ 作用于其他类型(比如 n 类型) # print(\'字符串:{0:_n}\'.format(1234567)) \"\"\" ValueError: Cannot specify \',\' with \'n\'. \"\"\"
5.7 精度
精度:
精度指定了小数点后面要展示多少位小数
对于非数字类型,精度指定了最大字段宽度
整数类型不能指定精度
# 对于非数字类型,精度指定最大字段宽度 print(\'{0:.3}\'.format(\'哇哈哈哈哈哈\')) \"\"\" 哇哈哈 \"\"\" # 整数类型不能指定精度 print(\'{:.3d}\'.format(666)) \"\"\" ValueError: Precision not allowed in integer format specifier \"\"\"
5.8 类型码
类型码可以分为三大类:
字符串类型
整数类型
浮点数类型
5.8.1 字符串类型
s 字符串类型。这是字符串的默认类型,可以省略。
None 不指定类型。同 s 类型。
# s 类型 print(\'{0:s}\'.format(\'略略略\')) # s 类型可以省略 print(\'{0:}\'.format(\'略略略\')) \"\"\" 略略略 略略略 \"\"\"
5.8.2 整数类型
b 二进制。
# b 类型:二进制 print(\'{0:b}\'.format(3)) \"\"\" 11 \"\"\"
c 字符。把整数转换为相应的 Unicode 字符,然后再打印。
# c 类型:把整数转换成 unicode 字符 print(\'{:c}\'.format(97)) \"\"\" a \"\"\"
d 十进制整数。
# d 类型:十进制整数 print(\'{:d}\'.format(666)) \"\"\" 666 \"\"\"
o 八进制数。
# o 类型:八进制数 print(\'{:o}\'.format(10)) \"\"\" 12 \"\"\"
x 十六进制数,a 到 f 小写。
# x 类型:十六进制数,a到f小写 print(\'{:x}\'.format(15)) \"\"\" f \"\"\"
X 十六进制数,A 到 F 大写。
# X 类型:十六进制数,A到F大写 print(\'{:X}\'.format(15)) \"\"\" F \"\"\"
n 数字 number 类型,与 d 相同,只不过它会使用本地化的数字分隔符。
经试验,在本机为 n 类型指定任何分组选项(, 和 _)都会报错。
ValueError: Cannot specify \',\' with \'n\'.
# n 类型:与d相同,会插入本地化的分隔符 print(\'{:n}\'.format(66666)) # 经试验,本机无法为 n 指定任何分组选项(,_) # print(\'{:,n}\'.format(66666)) \"\"\" ValueError: Cannot specify \',\' with \'n\'. \"\"\" # print(\'{:_n}\'.format(66666)) \"\"\" ValueError: Cannot specify \',\' with \'n\'. \"\"\"
None 不指定类型,与 d 相同。
5.8.3 浮点数类型
e 科学记数法,用 e 来表示指数。默认精度为 6 位
# e 类型:科学记数法 # 默认精度为 6 位 print(\'{:e}\'.format(1234567.1234567)) \"\"\" 1.234567e+06 \"\"\"
E 与 e 相同,但是使用大写的 E 表示指数。
# E 类型:与 e 相同,用大写 E 表示指数 # 默认精度为 6 位 print(\'{:E}\'.format(1234567.1234567)) # 修改精度为 10 位 print(\'{:.10E}\'.format(1234567.1234567)) \"\"\" 1.234567E+06 1.2345671235E+06 \"\"\"
f 定点记法,默认精度为 6。
# f 类型 # 默认精度为 6 位 print(\'{:f}\'.format(1234567.1234567)) \"\"\" 1234567.123457 \"\"\"
F 定点记法,同 f,但是会把 nan 转换成 NAN,把 inf 转换成 INF
# F 类型 nan = float(\'nan\') inf = float(\'inf\') print(\'{:F}\\n{:F}\'.format(nan, inf)) \"\"\" NAN INF \"\"\"
g 通用 general 格式。自动转换到 e 或者 f 格式,具体的转换规则在此省略。正无穷、负无穷、正零、负零和非数字分别显示为 inf,-inf,0,-0,nan。指定精度为 0 时等价于精度为 1。默认精度为 6 位。
# g 类型 print(\'{:g}\'.format(1234567.1234567)) print(\'{:g}\'.format(1234.1234)) \"\"\" 1.23457e+06 1234.12 \"\"\"
G 通用 general 格式。自动转换到 E 或者 F 格式,转换规则同上,相应表示方式换成大写。
# g 类型 print(\'{:g}\'.format(1234567.1234567)) print(\'{:g}\'.format(1234.1234)) \"\"\" 1.23457e+06 1234.12 \"\"\"
n 数字 number 类型。跟 g 一样,只不过用本地化的分隔符来分隔数字。
# n 类型 print(\'{:n}\'.format(1234567.1234567)) print(\'{:n}\'.format(1234.1234)) \"\"\" 1.23457E+06 1234.12 \"\"\" # 经试验,本机指定分组选项会报错 # print(\'{:,n}\'.format(1234.1234)) \"\"\" ValueError: Cannot specify \',\' with \'n\'. \"\"\" # print(\'{:_n}\'.format(1234.1234)) \"\"\" ValueError: Cannot specify \',\' with \'n\'. \"\"\"
% 百分号类型。会将数字乘以 100,然后以 f 定点 fixed-point 格式显示,最后加上一个百分号 %。
# % 类型 print(\'{:%}\'.format(1)) \"\"\" 100.000000% \"\"\"
None 不指定类型。输出效果类似调用 str() 函数。
6. 补充说明
输出花括号需要用花括号本身来转义
# 打印花括号需要使用花括号转义 print(\'{{{}}}\'.format(\'张无忌\')) \"\"\" {张无忌} \"\"\"
对象可以自定义格式说明符来替换标准格式说明符,比如 datetime 类。
from datetime import datetime print(\"Today is: {0:%a %b %d %H:%M:%S %Y}\".format(datetime.now())) \"\"\" 今天是:Thu Nov 15 13:05:09 2018 \"\"\"
参考资料
Format String Syntax
PEP 3101 – Advanced String Formatting
Python format 格式化函数
Python之format详解
Python高级编程
暂无评论内容