4.2 字符串格式化
到目前为止,我们对字符串的操作都停留在赋值、重新赋值、索引、分片和输出等一些比较基本的操作上,其实字符串还有更多、更好的操作方式,比如在实际项目开发中经常使用的字符串格式化操作。
4.2.1 字符串格式化符号
字符串格式化使用操作符百分号(%)实现。
提 示
%也可以用作模运(求余)操作符。
例如:
>>> print ('hello,%s' % 'world') hello,world >>> print ('小智今年%s岁了' % 10) 小智今年10岁了
由上面输入的内容可知,%左边放置了一个待格式化的字符串,右边放置的是希望格式化的值。格式化的值可以是一个字符串或数字。
格式化字符串的%s部分称为转换说明符,标记了需要放置转换值的位置,通用术语为占位符。可以想象成在学校上自习,我们通常会放一个物品在一个位置上,其他人一看就知道这个位置被占了,而我们无论什么时候去自习,直接到自己占好的位置坐下即可。这里可以把%s当作我们使用的物品,我们相当于后面%右边的值。
在上面的示例中,s表示百分号右边的值会被格式化为字符串,s指的是str。如果不是字符串,就会使用str将其转换为字符串。示例中就将10转换为字符串了,这种方式对大多数数值都有效。
这里提供了字符串格式化的方式,但若需要转换为其他格式,该怎么办呢?Python为我们提供了表4-2所示的格式化符号。
表4-2 字符串格式化符号
根据表4-2,前面的示例可以使用以下两种方式:
>>> print ('小智今年%s岁了' % 10) #使用%s作为10的占位符 小智今年10岁了 >>> print ('小智今年%d岁了' % 10) #使用%d作为10的占位符 小智今年10岁了
由操作结果看到,整数既可以使用%s也可以使用%d进行格式化。
如果要格式化实数(浮点数),就可以使用%f进行格式化,例如:
>>> print ('圆周率PI的值为:%f' % 3.14) 圆周率PI的值为:3.140000
输出结果中有很多位小数,但传入的值只有两位小数,要解决这个问题可以使用格式化符号。
从表4-2可知,%f可指定精度值。在Python中,使用%f时,若不指定精度值,则默认输出6位小数。
以指定2位小数为例,指定精度值的格式如下:
%.2f
指定精度值的格式为一个英文格式下的句点加上希望保留的小数位数。因为格式化说明符以表示类型的字符结束,所以精度值应该放在类型字符前面。
使用这个格式更改上面圆周率输出的示例:
>>> print ('圆周率PI的值为:%.2f' % 3.14) 圆周率PI的值为:3.14
输出结果正是我们希望得到的。
表4-2中的符号不是所有都常用,比较常用的有%s、%d、%f三个,%e和%E在科学计算中使用比较多,其他符号了解就可以,有兴趣也可以自行研究。
假如我们要输出类似1.23%这样的结果,直接使用加号加一个百分号可以吗?尝试如下:
>>> print ('小智的识别能力比去年提高了:%.2f' % 1.23+'%') 小智的识别能力比去年提高了:1.23%
输出结果得到了我们想要的,说明这种方式可以。不过输入的代码看起来怪怪的,有没有更好的办法呢?例如:
>>> print ('小智的识别能力比去年提高了:%.2f%%' % 1.23) 小智的识别能力比去年提高了:1.23%
用这种方式也得到了我们想要的结果。不过我们在f字符后面使用了两个%,结果只输出了一个,这是怎么回事?
在Python中,字符串中的百分号是转换说明符,如果要输出%,就需要格式化字符%,从而需要使用%%。使用这种方式操作的功能类似:
>>> print ('输出百分号:%s' % '%') 输出百分号:%
4.2.2 字符串格式化元组
格式化操作符的右操作数可以是任何元素。如果是元组或映射类型(如字典,第5章进行讲解),那么字符串格式化将会有所不同。我们尚未涉及映射(字典),这里先了解一下元组。
如果右操作数是元组,其中每一个元素都会被单独格式化,每个值都需要一个对应的转换说明符,例如:
>>> print ('今年是%s年,中国女排夺得本届奥运会%s,中国共获得%d枚金牌'%('2016','冠军',26)) 今年是2016年,中国女排夺得本届奥运会冠军,中国共获得26枚金牌 >>> print ('今年是%s年,中国女排夺得本届奥运会%s,中国共获得%d枚金牌' % '2016','冠军',26) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: not enough arguments for format string
由以上输出结果看到,在有多个占位符的字符串中,可以使用元组传入多个格式化值。如果需要转换的元组作为转换表达式的一部分存在,就必须将它用圆括号括起来,否则会出错。
提 示
如果使用列表或其他序列代替元组,序列就会被解释为一个值。只有元组和字典可以格式化一个以上的值。
下面介绍基本转换说明符。注意,这些项的顺序是至关重要的。
(1)%字符:标记转换说明符开始。
(2)转换标志(可选):-表示对齐;+表示在转换值之前要加上正负号;“”(空白字符)表示正数之前保留空格;0表示转换值位数不够时用0填充。
(3)最小字段宽度(可选):转换后的字符串至少应该具有该值指定的宽度。如果是*,宽度就会从值元组中读出。
(4)点(.)后跟精度值(可选):如果转换的是实数,精度值表示出现在小数点后的位数;如果转换的是字符串,该数字就表示最大字段宽度;如果是*,精度就会从元组中读出。
(5)转换类型:参见表4-2。
下面将详细讨论上述5个注意项。
1. 简单转换
例如,输入以下代码:
>>> print ('圆周率PI的值为:%.2f' % 3.14) 圆周率PI的值为:3.14 >>> print ('石油价格为每桶:$%d' % 96) 石油价格为每桶:$96
由上面的输出结果可以看到,简单转换只需要写出转换类型,使用起来很简单。
2. 字段宽度和精度
转换说明符包括字段宽度和精度。字段宽度是转换后的值所保留的最小字符个数,精度是数字转换结果中应该包含的小数位数或字符串转换后的值所能包含的最大字符个数。
例如:
>>> print ('圆周率PI的值为:%10f' % 3.141593) #字段宽度为10 圆周率PI的值为: 3.141593 #字符串宽度为10,被字符串占据8个空格,剩余两个空格 >>> print ('保留2位小数,圆周率PI的值为:%10.2f' % 3.141593) #字段宽度为10 保留2位小数,圆周率PI的值为: 3.14 #字符串宽度为10,字符串占据4个,剩6个 >>> print ('保留2位小数,圆周率PI的值为:%.2f' % 3.141593) 保留2位小数,圆周率PI的值为:3.14 #输出,没有字段宽度参数 >>> print ('字符串精度获取:%.5s' % ('hello world')) #打印字符串前5个字符 字符串精度获取:hello
由输出结果可知,字段宽度和精度都是整数,并通过点号(.)分隔。两个都是可选参数,如果给出精度,就必须包含点号。
再看以下代码:
>>> print ('从元组中获取字符串精度:%*.*s' % (10,5,'hello world')) 从元组中获取字符串精度: hello #输出字符串宽度为10、精度为5 >>> print ('从元组中获取字符串精度:%.*s' % (5,'hello world')) 从元组中获取字符串精度:hello #输出精度为5
由输出结果看到,可以使用*(星号)作为字段宽度或精度(或两者都用*),数值会从元组中读出。
3. 符号、对齐和0填充
开始介绍之前先看一个示例:
>>> print ('圆周率PI的值为:%010.2f' % 3.141593) 圆周率PI的值为:0000003.14
输出结果是不是怪怪的,这个我们称之为“标表”。在字段宽度和精度之前可以放置一个“标表”,可以是零、加号、减号或空格。零表示用0进行填充。
减号(-)用来左对齐数值,例如:
>>> print ('圆周率PI的值为:%10.2f' % 3.14) 圆周率PI的值为: 3.14 >>> print ('圆周率PI的值为:%-10.2f' % 3.14) 圆周率PI的值为:3.14 #此处右侧为多出的空格
从输出结果看到,使用减号时,数字右侧多出了额外的空格。
空白(“ ”)表示在正数前加上空格,例如:
>>> print(('% 5d' % 10)+'\n'+('% 5d' % -10)) 10 -10
由输出结果可以看到,该操作可以用于对齐正负数。
加号(+)表示无论是正数还是负数都表示出符号,例如:
>>> print(('宽度前加加号:%+5d'%10)+'\n'+('宽度前加加号:%+5d'%-10)) 宽度前加加号: +10 宽度前加加号: -10
该操作也可以用于数值的对齐。
从Python 3.6开始,引入了一种新的字符串:_f-strings_,格式化字符串。格式化字符串带'f'前缀,类似于str.format()接受的格式化字符串。它们包含由花括号括起来的替换字段。替换字段是表达式,它们会在运行时计算,然后使用format()协议进行格式化。
_f-strings_使用方式如下:
>>> val_str = 'Python 3.7' >>> print(f'welcom to begin {val_str}') welcom to begin Python 3.7 >>> import decimal >>> width = 10 >>> precision = 4 >>> value = decimal.Decimal("12.34567") >>> f"result: {value:{width}.{precision}}" 'result: 12.35'