1.4 格式化字符串
案例13 输出十六进制字符串
导语
字符串的格式化方法是在字符串表达式前面加上前缀f,字符串表达式中需要进行格式化处理的部分用一对大括号包裹起来。大括号内可以是任意表达式,也可以引用其他变量。例如:
字符串表达式中的“{age}”就会被age变量的值替换,最终字符串表达式会变成
在大括号中,表达式之后可以使用格式控制符来定制字符的显示格式。格式控制符以一个冒号(英文标点)开头。例如,下面格式控制符表示一个浮点数的字符串形式,并且保留两位小数(形如“0.15”“73.08”等)。
产生的字符串为“0.13”。大括号中的f表示输出内容的类型为浮点数,小数位的设置必须以“.”开头,后面的数值即所保留的小数位数。
本案例希望输出数值的十六进制字符串,一般常见的格式为0xnnnn或者0XNNNN。只要把上面例子中的f改为x或者X,就可以将数值转换为十六进制的表示形式。X表明十六进制中的字母为大写(A、B、C、D、E、F),x则表明字母是小写(a、b、c、d、e、f)。
操作流程
步骤1:定义一个整数列表。
步骤2:通过for循环,将列表中的数值分别以十进制和十六进制的方式打印出来。
在输出十六进制的字符串时,格式控制符x前加上“#”符号,可以让输出的十六进制字符串前面加上“0x”,形如0x20e4c。
“6d”中的数字6表示生成的字符串宽度为6个字符,如果实际字符数小于6,则剩余空间用空格填充;“#8x”中的数字8的含义也一样,即生成的字符串宽度为8个字符。
步骤3:执行上述代码,得到如下结果。
其中,左边的数值为十进制,右边是与之对应的十六进制数值。
案例14 设置字符串的对齐方式
导语
在定制字符串格式时,可以指定字符串的对齐方式,使用到的字符为:“<”“>”“^”或“=”。其中,“<”表示左对齐,“>”表示右对齐,“^”表示居中对齐。另外,“=”比较特殊,它只用于数字类型。“=”控制符将数值的符号对齐到左边,把数值部分拉到右边,中间的空余部分由空格或者“0”填充。例如
操作流程
步骤1:输出三行字符串,对齐方式依次为左对齐、居中对齐和右对齐。为了让对齐效果更直观,设置字符串的总长度为30个字符。
字符串在对齐后,剩余的字符空间将用空格来填充。输出结果如下:
步骤2:输出三行字符,对齐方式依次为左对齐、居中对齐和右对齐,字符总宽度也设定为30。这一轮输出将使用“∗”符号来填充剩余空间。
把“∗”字符放在对齐控制符(“<”“>”等)之前,表示用该字符去进行剩余空间的填充。其输出结果如下:
步骤3:“=”对齐控制只适用于数值类型的格式(如“d”“x”等)。下面代码依次输出十六进制、八进制、十进制、二进制的数值,并使用“=”控制让其两端对齐。
输出结果如下:
在格式控制符中添加“#”字符的含义是:当呈现十六进制数值时会在字符串前面加上“0x”或“0X”;当呈现的是八进制的数值时,会在字符串前面加上“0o”;当呈现的数值是二进制时,会在字符串前面加上“0b”。
案例15 数字的千位分隔符
导语
每三位(千位)使用一个逗号分隔的数字格式多见于财务计算,在对字符串进行格式化时,只要在类型标志或宽度/小数位标志前面加上一个英文的逗号,输出的数字文本就会每三位(千位)插入一个英文的逗号。
逗号标志一般与d(十进制整数)或f(浮点数)一起使用,不能与n(常规数字)一起使用。因为n标志表示的数字格式是以区域/语言的本地化设置相关,与逗号标志连用可能会发生冲突。
操作流程
步骤1:声明变量,并赋值一个浮点数值。
步骤2:格式化为整数,并加上千位分隔符。
d标志符只能用于整型数值,因此需要调用int类的构造函数int(num)将浮点数值num转换为整数值。
输出结果如下:
步骤3:输出浮点数值,并加上千位分隔符。
输出结果如下:
步骤4:输出浮点数值,加上千位分隔符,并保留两位小数。
输出结果如下:
案例16 “_”分隔符
导语
下画线(_)分隔符的作用与逗号分隔符相同,可以对数值字符串进行分组。对于十进制数值,下画线每三位(千位)一组;而对于二进制、八进制、十六进制的数值字符串,下画线每四位一组。
操作流程
步骤1:声明变量并赋值。
步骤2:分别输出变量number的十进制、二进制、八进制、十六进制的字符串形式,以下画线作为分隔符。
步骤3:运行以上代码,得到如下结果。
案例17 自定义日期格式
导语
常用的日期/时间格式控制符如表1-1所示。
表1-1 常用日期时间格式控制符
操作流程
步骤1:导入datetime模块。
步骤2:案例化一个date对象,它表示日期数据。
调用构造函数时传递的参数依次为年、月、日。
步骤3:输出形如“2015-9-15”的格式。
步骤4:输出形如“2015年9月15日”的格式。
步骤5:案例化一个time对象,它表示时间数据。
传递给time类构造函数的参数值依次为时、分、秒。
步骤6:输出本地化的时间格式。
上述代码执行后的输出结果如下:
案例18 使用format方法
导语
字符串类型(str)有一个format案例方法,也可以对字符串进行格式化,使用方法与f前缀基本相同(差别主要在调用方式上,格式控制符的用法是完全一样的)。
在带格式化控制符的字符串中,可以使用序号或者命名方式定义占位符,然后调用字符串案例的format方法,并将要替换占位符的实际内容通过format方法的参数传递。举个例子,请读者思考以下代码:
上述字符串中有两处占位符,序号从0开始。调用format方法时传递两个参数,第一个参数“Dick”替换字符串中的“{0}”,第二个参数“重庆”替换字符串中的“{1}”,于是,调用得到的新字符串为“我叫Dick,我来自重庆”。
当然,占位符也可以不用序号,而是直接取个名字,例如
如果占位符是命名的,那么在调用format方法时必须以关键字方式来传递参数,即必须写上参数名称。这些参数的名字与数量取决于原字符串中的占位符,必须一一匹配。例如,在上面代码中,字符串中有命名的为“who”的占位符,在调用format方法时,用“Lucy”进行替换;同理,参数count用7替换字符串中的“count”占位符,最终得到新字符串案例“你好,Lucy,你已完成7项任务”。
操作流程
步骤1:分别以十进制和二进制来显示同一个数值。
虽然字符串中有两处占位符,但它们的序号相同,因此,在format方法调用时,只要传递一个参数即可。
步骤2:以下字符串中有三处占位符。
参数值“1.png”替换字符串中的“{0}”,参数值“Bob”替换字符串中的“{1}”,参数值315073(整数值)替换字符串中的“{2}”(int类型的值自动转换为字符串)。
步骤3:再看看带有命名占位符的字符串。
“lang1”被“C++”替换,“lang2”被“Python”替换。
以上代码运行后的输出结果如下:
案例19 省略格式占位符的名称和序号
导语
通过调用format方法进行字符串格式化时,字符串中的占位符是可以省略其序号或者名称的。这种情况下,传递给format方法的参数的顺序,必须与占位符在字符串中出现的顺序一致。例如:
格式占位符只用一对空白的大括号表示,format方法调用时所传递的参数值,会按照占位符出现的顺序进行替换。即:第一对大括号被整数值3替换,第二对大括号被整数值7替换。
操作流程
步骤1:声明三个变量。
变量a和b明确进行赋值,变量c的值来自于变量a和b的和。
步骤2:调用format方法进行字符串格式化。
在字符串表达式中,出现了三个占位符,但它们的序号(或名称)被省略。接下来必须向format方法传递三个参数值,用来依次替换字符串案例中的占位符。经格式化处理后输出的结果如下:
步骤3:声明一个变量,使用十进制的整数赋值(int类型)。
步骤4:输出格式化字符串。变量dc的值在字符串表达式中出现两次,第一次显示为十进制整数值,第二次显示为八进制整数值。
虽然占位符的序号(或名称)被省略了,但使用格式控制符时依然要以英文冒号开头。变量dc在字符串案例中出现两次,尽管是同一个值,但在调用format方法时仍然要按照占位符出现的顺序和次数传递参数,所以变量dc被传递了两次。
格式化后的输出结果如下:
案例20 字符串模板
导语
字符串模板允许在字符串中定义占位符,然后用具体的内容将占位符替换,此方案与字符串格式化类似。但字符串模板仅仅定义占位符,不定义格式控制符。
模板占位符的定义格式为:
即以字符“$”开头,后面紧跟着的是占位符的名称。例如:
如果占位符city的值为“天津”,那么由以上模板产生的字符串为“我来自天津”。如果字符中本身包含“$”字符,并非作为模板占位符名称,那么可以连用两个“$”来注明,也就是说,“$$”不会被识别为占位符。
占位符的名称有时候需要加上大括号,主要应用场景是:占位符名称与其他字符混合使用时,例如:
这时候不容易确认占位符的名字是叫“o”,还是叫“os”或是“ose”,这种情况下,就需要使用大括号了,假设占位符的名字是“os”,那该字符串模板就要写成:
字符串模板的使用方法是引入string模块中的Template类,将作为模板的字符串案例传递给Template类的构造函数,最后调用Template案例的substitute方法将字符串模板中的占位符替换并产生新的字符串案例。
操作流程
步骤1:导入string模块。
步骤2:案例化一个字符串模板。
步骤3:对上述模板中的“what”占位符进行两次替换。
第一次替换时,用“白云”替换掉模板中的“what”占位符,产生的新字符串案例为“天空飘着几朵白云”;第二次替换时,“what”占位符被“乌云”替换,产生字符串“天空飘着几朵乌云”。
步骤4:再案例化一个字符串模板。
这种情况下,占位符“len”必须使用大括号来包裹,否则占位符名字会被识别为“leninch”,当替换“len”时会发生错误。
步骤5:将模板中的“len”占位符替换为具体的内容。
步骤6:本案例运行后输出的结果如下:
案例21 字符串模板的安全替换模式
导语
string.Template类还公开了一个safe_substitute方法,此方法与substitute方法的功能相同——替换掉字符串模板中的占位符。但是,如果模板中的占位符数量与传递给substitute方法的参数不匹配,就会发生错误。这时就可以改用safe_substitute方法,该方法只替换参数与模板中能匹配的部分占位符,其余占位符将被忽略,不会引发错误。
操作流程
步骤1:导入Template类。
步骤2:定义字符串模板。
步骤3:调用safe_substitute方法替换占位符。
上述调用中,只对名为“who”的占位符进行替换,但名为“football”的占位符没有被替换。尽管提供的方法参数与模板不完全匹配,但不会发生错误。
步骤4:模板替换后产生的字符串如下:
案例22 文本缩进
导语
textwrap模块提供了对字符串做换行、截断、缩进处理的API。本案例将使用到indent函数,它的原型如下:
text参数指定等待处理的字符串案例(即原字符串)。prefix参数指定用作缩进的填充字符,例如空格。predicate参数是可选的,它可以引用一个函数,或者使用lambda表达式。predicate参数用于控制某一行是否允许缩进。当indent函数通过换行符(\n)分析出一行文本后,会将该行文本传递给predicate参数所引用的函数进行判断,如果允许缩进就返回True,否则返回False。
操作流程
步骤1:导入textwrap模块。
步骤2:声明变量并赋值,表示待处理的原字符串。
文本中带有两个换行符,indent函数分析时会将它拆为三行。
步骤3:对文本进行缩进处理,缩进字符用加号填充。
处理的结果如下:
步骤4:有时候,会考虑跳过空行,即空白的行不缩进。例如这个字符串:
上述文本中连用三个换行符,即产生了两个空白行。
步骤5:定义一个ignoreETLines函数,将空白行过滤掉。
如果一个行的文本中只有“\n”或“\r”字符,可以认为是空白的行,不应该进行缩进处理,于是返回False。
步骤6:对source2文本进行缩进处理,缩进填充字符为星号。
predicate参数引用刚刚定义的ignoreETLines函数,indent函数会自动调用它并把分解出来的每一行传给它。
处理结果如下:
从运行结果可以看出,中间两个空白行没有做缩进处理。
案例23 嵌套使用格式化语法
导语
为了使字符串的格式化变得更灵活,可以嵌套使用格式化的表达语法。例如:
其中,str是要进行格式化处理的变量,width是另一个变量的值,可以指定格式化后字符串的宽度(长度),最后d表示显示为十进制数值。
字符串宽度引用另一个变量的值,可以动态控制字符串的格式化结果而无须重新编写格式化字符串。例如,假设width变量的值为55,那么,字符串格式化表达式就会变为:
要是width变量的值被修改为40,那么格式化表达式就会变为:
嵌套格式化语法同样可以用于str.format方法中。例如:
在调用format方法时,数值200替换字符串中序号为0的占位符,其中,外层大括号中嵌套了一层大括号,包括字段wd,width变量的值替换字符串中的wd字段。相当于
操作流程
本案例需要用户进行两次输入:首先让用户输入一个整数值,然后再让用户输入格式化类型,即要以何种格式来显示该数值(如d表示十进制数值,b表示二进制数值)。最后,应用程序按照前面的两次输入向屏幕打印整数值的相应格式。
步骤1:调用input函数,获取用户输入的整数值。
步骤2:判断所输入的内容是否有效,如果无效,给出错误提示。
步骤3:如果输入的整数值有效,就提示用户输入要处理的格式类型。
步骤4:验证输入的类型是否有效,若有效,就对整数值格式化并打印到屏幕上。
valtypes变量是一个元组案例,它包含b、x、o三个元素,如果用户输入的字符与这三个元素中的一个相同,则说明输入有效,否则是无效值。
由于b、x、o格式控制符不支持字符串类型的变量,因此在进行格式化之前需要写上这一行代码,将num变量的值转换为int类型。
步骤5:运行案例,先输入一个十进制的整数值,例如160,然后输入“b”,就会打印出160对应的二进制值。