学Python数据科学,玩游戏、学日语、搞编程一条龙。
整套学习自学教程中应用的数据都是《三國志》、《真·三國無雙》系列游戏中的内容。
Python 来格式化字符串有 .format() 字符串方法 和 f-string 方法。
字符串.format() 方法
Python 2.6版本引入了字符串 .format() 方法。
调用模式有固定的模板,<positional_arguments> 和 <keyword_arguments> 指定插入的值 <template> 以代替替换的字段。
生成的格式化字符串是方法的返回值。
<template>.format(<positional_argument(s)>, <keyword_argument(s)>)
在 <template> 字符串中,替换字段用大括号 ( {} ) 括起来。
'{
{ {} }}'.format('曹操')
'{ 曹操 }'
字符串.format() 参数
位置参数,字符串模运算符和 string.format() 方法。
print('%d 天需要造%s %.2f 万支' % (3, '箭', 10.0))
3 天需要造箭 10.00 万支
print('{0} 天需要造{1} {2} 万支'.format(3, '箭', 10.0))
3 天需要造箭 10.0 万支
<template> 进行数据格式化示意图。
位置参数被插入到模板中以代替编号的替换字段。
'{0}/{1}/{2}'.format('曹操', '孫権', '劉備')
'曹操/孫権/劉備'
替换字段可以按任何顺序指定出现在模板中,并且可以出现多次。
'{2}.{1}.{0}/{0}{0}.{1}{1}.{2}{2}'.format('曹操', '孫権', '劉備')
'劉備.孫権.曹操/曹操曹操.孫権孫権.劉備劉備'
超出范围的替换字段编号时会出现错误。
'{3}'.format('曹操', '孫権', '劉備')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
自动字段编号和参数不匹配时的情况。
# 字符串数量 < 编号数量
'{}{}{}{}'.format('曹操','孫権','劉備')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
# 字符串数量 > 编号数量
'{}{}'.format('曹操', '孫権', '劉備')
'曹操孫権'
两种方法不可以混合使用。
'{1}{}{0}'.format('曹操','孫権','劉備')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot switch from manual field specification to automatic field numbering
关键字参数,关键字参数被插入到模板字符串中,以代替具有相同名称的关键字替换字段。
使用关键字参数格式化输出。
print('{num_day} 天需要造{item} {num_item} 万支'.format(
num_day = 3,
item = '箭',
num_item = 10.0
))
缺少关键字会出现错误。
'{x}/{y}/{w}'.format(x='曹操', y='孫権', z='劉備')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'w'
按任意顺序指定关键字参数。
'{0}/{1}/{2}'.format('曹操', '孫権', '劉備')
'曹操/孫権/劉備'
'{0}/{1}/{2}'.format('孫権', '劉備', '曹操')
'孫権/劉備/曹操'
'{x}/{y}/{z}'.format(x='曹操', y='孫権', z='劉備')
'曹操/孫権/劉備'
'{x}/{y}/{z}'.format(y='孫権', z='劉備', x='曹操')
'曹操/孫権/劉備'
位置参数必须出现在任何关键字参数之前。
'{0}{x}{1}'.format('曹操', '孫権', x='劉備')
'曹操劉備孫権'
'{0}{x}{1}'.format('曹操', x='劉備', '孫権')
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
指定变量方法进行输出。
x = '曹操'
y = '孫権'
z = '劉備'
'{0}/{1}/{s}'.format(x, y, s=z)
'曹操/孫権/劉備'
字符串.format() 直接替换字段
调用 Python 的.format()方法时 <template> 字符串包含替换字段。这些指示在模板中将参数插入方法的位置。
替换字段由三个部分组成。
"""
{[<name>][!<conversion>][:<format_spec>]}
<name> 指定要格式化的值的来源
<conversion> 指示用于执行转换的标准 Python 函数
<format_spec> 指定有关如何转换值的更多详细信息
"""
<name>组件,由位置参数的数字,或者是关键字参数的关键字组成。
x, y, z = 1, 2, 3
'{0}, {1}, {劉備}'.format(x, y, 劉備=z)
'1, 2, 3'
参数是列表访问列表的元素。
list_ = ['曹操', '孫権', '劉備']
'{0[0]}, {0[2]}'.format(list_)
'曹操, 劉備'
'{my_list[0]}, {my_list[2]}'.format(my_list=list_ )
'曹操, 劉備'
参数是字典访问字典的元素。
dict_ = {
'key1': '曹操', 'key2': '孫権'}
dict_['key1']
'曹操'
'{0[key1]}'.format(dict_)
'曹操'
dict_ ['key2']
'孫権'
'{my_dict[key2]}'.format(my_dict=dict_ )
'孫権'
参数是对象访问对象的属性。
z = 3+5j
type(z)
<class 'complex'>
z.real
3.0
z.imag
5.0
z
(3+5j)
'real = {0.real}, imag = {0.imag}'.format(z)
'real = 3.0, imag = 5.0'
<conversion>组件,数据强制转换 str() 强制转换方法。
'{0!s}'.format(42) # !s 转换为str()
'42'
'{0!r}'.format(42) # !r 转换为repr()
'42'
'{0!a}'.format(42) # !a 转换为ascii()
'42'
<format_spec>组件,包含的信息可以很好地控制在插入模板字符串之前如何格式化值。
"""
:[[<fill>]<align>][<sign>][#][0][<width>][<group>][.<prec>][<type>]
"""
<align>组件,控制如何在指定的字段宽度内填充和定位格式化输出,这些子组件只有在格式化的字段值不占据整个字段宽度时才有意义。
# 小于号 (<) 的值表示输出是左对齐的
'{0:<8s}'.format('曹操')
'曹操 '
'{0:<8d}'.format(123)
'123 '
# 大于号(>)的值表示输出应右对齐
'{0:>8s}'.format('曹操')
' 曹操'
'{0:>8d}'.format(123)
' 123'
# 符号(^)的值表示输出应位于输出字段的中心
'{0:^8s}'.format('曹操')
' 曹操 '
'{0:^8d}'.format(123)
' 123 '
# 符号(=)为<align>子组件指定一个值
'{0:+8d}'.format(123)
' +123'
'{0:=+8d}'.format(123)
'+ 123'
'{0:+8d}'.format(-123)
' -123'
'{0:=+8d}'.format(-123)
'- 123'
<fill> 组件,指定当格式化的值没有完全填满输出宽度时如何填充额外的空间。
'{0:->8s}'.format('曹操')
'-----曹操'
'{0:#<8d}'.format(123)
'123#####'
'{0:*^8s}'.format('曹操')
'**曹操***'
<sign>组件,控制符号是否与组件一起出现在数字输出。
# 加号 (+) 正负值始终都包含一个符号。
'{0:+6d}'.format(123)
' +123'
'{0:+6d}'.format(-123)
' -123'
# 单个空格 (' ') 表示负值包含符号。
'{0:*> 6d}'.format(123)
'** 123'
'{0:*>6d}'.format(123)
'***123'
'{0:*> 6d}'.format(-123)
'**-123'
# 组件,哈希字符 ( # ) 会导致在值左侧包含显式基本指示符。
# 对于二进制、八进制和十六进制表示类型
'{0:b}, {0:#b}'.format(16)
'10000, 0b10000'
'{0:o}, {0:#o}'.format(16)
'20, 0o20'
'{0:x}, {0:#x}'.format(16)
'10, 0x10'
# 对于浮点或指数表示类型
'{0:.0f}, {0:#.0f}'.format(123)
'123, 123.'
'{0:.0e}, {0:#.0e}'.format(123)
'1e+02, 1.e+02'
0 组件,如果输出小于指定的字段宽度,并且指定数字零 ( 0 ),则值将在左侧填充零而不是 ASCII 空格字符。
'{0:05d}'.format(123)
'00123'
'{0:08.1f}'.format(12.3)
'000012.3'
# 适用于字符串值。
'{0:>06s}'.format('曹操')
'000曹操'
<width>组件,指定输出字段的最小宽度。
'{0:8s}'.format('曹操')
'曹操 '
'{0:8d}'.format(123)
' 123'
# 指定的值比最小值长则忽略。
'{0:2s}'.format('曹操孫権')
'曹操孫権'
<group>组件,在数字输出中包含分组分隔符,可以指定为逗号字符 ( , ) 或下划线字符 ( _ )。
'{0:,d}'.format(1234567)
'1,234,567'
'{0:_d}'.format(1234567)
'1_234_567'
'{0:,.2f}'.format(1234567.89)
'1,234,567.89'
'{0:_.2f}'.format(1234567.89)
'1_234_567.89'
# 二进制、八进制和十六进制表示类型指定。
'{0:_b}'.format(0b111010100001)
'1110_1010_0001'
'{0:#_b}'.format(0b111010100001)
'0b1110_1010_0001'
'{0:_x}'.format(0xae123fcc8ab2)
'ae12_3fcc_8ab2'
'{0:#_x}'.format(0xae123fcc8ab2)
'0xae12_3fcc_8ab2'
.<prec>组件,指定浮点表示类型的小数点后的位数。
'{0:8.2f}'.format(1234.5678)
' 1234.57'
'{0:8.4f}'.format(1.23)
' 1.2300'
'{0:8.2e}'.format(1234.5678)
'1.23e+03'
'{0:8.4e}'.format(1.23)
'1.2300e+00'
# 对于字符串类型,.<prec>指定转换输出的最大宽度
'{:.4s}'.format('曹操孫権')
'曹操b'
<type>组件,表示字符的转换类型。
"""
b 二进制整数
c 单个字符
d 十进制整数
e、E 指数的
f、F 浮点
g、G 浮点数或指数
o 八进制整数
s 细绳
x、X 十六进制整数
% 百分比
"""
'%d' % 42
'42'
'{:d}'.format(42)
'42'
'%f' % 2.1
'2.100000'
'{:f}'.format(2.1)
'2.100000'
'%s' % '曹操孫権'
'曹操孫権'
'{:s}'.format('曹操孫権')
'曹操孫権'
'%x' % 31
'1f'
'{:x}'.format(31)
'1f'
.format() 中表示类型和字符串模运算符转换类型之间存在一些细微差。
# 类型 b 字符串格式化差异,类型 i,u 字符串格式化差异。
# 二进制整数转换
'{:b}'.
format(257)
'100000001'
# 模运算符,不支持
'%b' % 257
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: unsupported format character 'b' (0x62) at index 1
# 类型 c 字符串格式化差异。
# 模运算符允许具有转换类型的整数或单个字符值
'%c' % 35
'#'
'%c' % '#'
'#'
# 要求表示类型对应的值c是整数
'{:c}'.format(35)
'#'
'{:c}'.format('#')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'c' for object of type 'str'
# 类型 g, G 字符串格式化差异。
'{:g}'.format(3.14159)
'3.14159'
'{:g}'.format(-123456789.8765)
'-1.23457e+08'
'{:G}'.format(-123456789.8765)
'-1.23457E+08'
# 类型 r, a 字符串格式化差异,分别强制转换 **repr()** 和 **ascii()** 。
repr({
1: 4, 2: 5}) # '{1: 4, 2: 5}'
repr(tuple) # "<class 'tuple'>"
repr("string") # "'string'"
repr("我是 ascii") # '我是 ascii'
ascii({
1: 4, 2: 5}) # '{1: 4, 2: 5}'
ascii(tuple) # "<class 'tuple'>"
ascii("string") # "'string'"
ascii("我是 ascii") # "'\\u6211\\u662f ascii'"
# 类型 % 字符串格式化差异,使用带模运算符的%转换类型在输出中插入文字 **%** 字符。
'%f%%' % 65.0
'65.000000%'
'{:%}'.format(0.65)
'65.000000%'
字符串.format() 嵌套替换字段
将关键字参数与嵌套替换字段一起使用。
w = 10
p = 2
'{val:{wid}.{pr}f}'.format(wid=w, pr=p, val=123.456)
' 123.46'
分组字符<group>是嵌套的 。
'{0:{grp}d}'.format(123456789, grp='_')
'123_456_789'
'{0:{grp}d}'.format(123456789, grp=',')
'123,456,789'
格式化字符串文字(f-String)
f 字符串语法
# f-string看起来很像一个典型的 Python 字符串
f'曹操 孫権 劉備'
'曹操 孫権 劉備'
# 可以使用大写字母F
s = F'曹操 孫権 劉備'
s
'曹操 孫権 劉備'
# 表达式嵌套处理
s = '孫権'
print(f'曹操.{
s}.劉備')
曹操.孫権.劉備
# 转义序列处理
s = '孫権'
print(f'曹操\n{
s}\n劉備')
曹操
孫権
劉備
嵌入在 f 字符串不同的意义
# 变量
num_day,item,num_item = 3,'箭',10.0
f'{
num_day} 天需要造{
item} {
num_item} 万支'
'3 天需要造箭 10.0 万支'
# 算术表达式
num_day,item,num_item = 3,'箭',10.0
f'每天需要造{
item} {
num_item/num_day} 万支'
'每天需要造箭 3.3333333333333335 万支'
# 复合类型的对象
a = ['曹操', '孫権', '劉備']
d = {
'曹操': 1, '孫権': 2}
print(f'a = {
a} | d = {
d}')
"a = ['曹操', '孫権', '劉備'] | d = {'曹操': 1, '孫権': 2}"
# 索引、切片和关键引用
a = ['曹操', '孫権', '劉備']
d = {
'曹操': 1, '孫権': 2}
print(f'{
a[0]}')
曹操
print(f'{
a[-2:]}')
['孫権', '劉備']
print(f'{
a[::-1]}')
['劉備', '孫権', '曹操']
print(f"{
d['孫権']}")
2
# 函数和方法调用
a = ['曹操', '孫権', '劉備']
print(f' {
len(a)} items')
3 items
# 条件表达式
age = 29
f'諸葛亮 {
"已出山" if age > 27 else "未出山"}。'
'諸葛亮 已出山。'
# 对象属性
z = 3+5j
z
(3+5j)
print(f'real = {
z.real}, imag = {
z.imag}')
real = 3.0, imag = 5.0
# 转义操作
z = '孫権'
print(f'曹操\n{
z}\n劉備')
曹操
孫権
劉備
print(rf'曹操\n{
z}\n劉備')
曹操\n孫権\n劉備
print(fr'曹操\n{
z}\n劉備')
曹操\n孫権\n劉備
# 模板.format()
z = '曹操孫権'
f'{
{ {
z[::-1]} }}'
'{ 権孫操曹 }''
f-String 表达式限制
# f-string 表达式不能为空
f'曹操{}孫権'
File "<stdin>", line 1
SyntaxError: f-string: empty expression not allowed
# f 字符串表达式不能包含反斜杠 ( \ ) 字符。
print(f'曹操{
\n}孫権')
File "<stdin>", line 1
SyntaxError: f-string expression part cannot include a backslash
print(f'曹操{
\'}孫権')
File "<stdin>", line 1
SyntaxError: f-string expression part cannot include a backslash
# 创建一个包含要插入的转义序列的临时变量来绕过此限制
nl = '\n'
print(f'曹操{
nl}孫権')
曹操
孫権
quote = '\''
print(f'曹操{
quote}孫権')
曹操'孫権
# 三引号的 f 字符串中的表达式不能包含注释
z = '孫権'
print(f'''曹操{
... z
... }劉備''')
曹操孫権劉備
print(f'''曹操{
... z # Comment
... }''')
File "<stdin>", line 3
SyntaxError: f-string expression part cannot include '#'
f 字符串格式
# 所有适用的< format_spec > 组件.format()也适用于 f 字符串。
n = 123
'{:=+8}'.format(n)
'+ 123'
f'{
n:=+8}'
'+ 123'
s = '曹操'
'{0:*^8}'.format(s)
'**曹操***'
f'{
s:*^8}'
'**曹操***'
n = 0b111010100001
'{0:#_b}'.format(n)
'0b1110_1010_0001'
f'{
n:#_b}'
'0b1110_1010_0001'
# 嵌套使用 Python.format()方法的嵌套替换字段
a = ['曹操', '孫権', '劉備']
w = 4
f'{
len(a):0{
w}d}'
'0003'