Python字符串格式化

时间:2020-02-23 14:43:25  来源:igfitidea点击:

在本教程中,我们将学习Python中可用的不同字符串格式化技术

  • 旧方法,即百分比(%)格式(在Python 2和3中受支持)

  • 新方法,即string.format()(Python 2.6及更高版本)

  • 最新方法,即f字符串-格式化的字符串文字(Python 3.6及更高版本)

百分比格式

C语言风格的%格式化是一种古老的,不建议使用的格式化字符串的方法,我们可能最终会在旧代码中看到。在这种方法中,使用%操作符来传递值。在字符串中,我们使用字符,后接格式说明符,以声明应如何插入该值;

示例1:使用%格式替换值

在此示例中,我们将执行字符串和整数的基本替换。

#!/usr/bin/env python3
name = 'hynman'
drink = 'coffee'
price = 3
message = 'Hey %s, this %s costs $%d.' % (name, drink, price)
print(message)

该脚本的输出:

~]# python3 percent-formatting.py
Hey hynman, This coffee costs .

其中

  • 字符串中的%s表示插入字符串%d表示将其替换为整数

  • 字符串中出现的%的数量必须与字符串后面的%之后的数据项的数量相匹配。

  • 单个数据项(例如name)紧跟在最后一个之后。

  • 必须将多个数据分组为一个元组,因为我们在括号内添加了名称,饮料,价格,并用逗号分隔

下表显示了替换键的可能格式。

转换意义
%d有符号整数十进制
%i有符号整数十进制
%u过时-与“d”相同
%o符号八进制值
%x有符号十六进制-小写
%X有符号十六进制-大写
%f浮点十进制
%e浮动点指数小写
%E浮点指数大写
%g如果指数小于-4或者不小于精度,浮点格式使用小写指数格式,否则使用十进制格式
%G如果指数小于-4或者不小于精度,浮点格式使用大写指数格式,否则使用十进制格式
%c单个字符
%r字符串(使用repr()转换有效的Python对象)
%s字符串(使用str()转换有效的Python对象)
%%未转换任何参数,结果为“%”字符

示例2:添加填充并对齐字符串的内容

我们可以在%和类型说明符之间的格式字符串中添加其他值,以指定"最小和最大宽度","对齐"和"字符填充"。

  • 初始的"%"字符。

  • 可选的对齐字符:无或者" +"表示右对齐,"-"表示左对齐。

  • 要使用的可选的minwidth字段宽度。

  • 可选的"。"字符,用于分隔" minwidth"和" maxchars"。

  • 可选的" maxchars"(如果转换类型为s),表示要从数据值中打印多少个字符。如果转换类型为" f",即浮点整数,则此参数指定精度(小数点后要打印多少位数字)。

这听起来可能令人困惑,而且从理论上讲都是如此,所以让我们在下一个示例中使用它:

#!/usr/bin/env python3
name = 'root'
message1 = 'How'
message2 = 'are you?'
## no extra padding
log = "Hey %s, %s %s " % (name, message1, message2)
print(log)
## added extra padding before message1
log = "Hey %s, %10s %s " % (name, message1, message2)
print(log)
## added extra padding before message1 and right aligned
log = "Hey %s, %+10s %s " % (name, message1, message2)
print(log)
## added extra padding before message1 and left aligned
log = "Hey %s, %-10s %s " % (name, message1, message2)
print(log)
## Max 3 characters allowed in message2
log = "Hey %s, %s %.3s " % (name, message1, message2)
print(log)
## min width is 10 and max character allowed is 3 in message2
log = "Hey %s, %s %10.3s " % (name, message1, message2)
print(log)

该脚本的输出:

~]# python3 string-formatting.py
Hey root, How are you?
Hey root,        How are you?
Hey root,        How are you?
Hey root, How        are you?
Hey root, How are
Hey root, How        are

其中

  • 第一个打印语句是默认输出,没有其他格式

  • 第二条打印语句-我们添加了其他填充空白。由于我们未指定+或者-,因此默认填充位于左侧

  • 第三个打印语句-我们使用+号将右侧的文本与定义的填充宽度对齐以提供相应的空格,因此输出类似于第二个打印语句

  • 第四个打印语句-我们正在使用-符号将左侧的文本与定义的填充宽度对齐以提供相应的空格,因此这次的'message1'在左侧与右侧的其他空格对齐。

  • 第五条打印语句-我们在message2中定义了一个字符限制,其中。 (点)充当分隔符。因此,仅打印消息2的前3个字母。由于我尚未定义任何填充,因此文本将使用默认填充进行打印

  • 第六条打印语句-我将字符限制与最小宽度(width.char limit)组合在一起,因此现在我们看到message2在左侧包含添加的空白填充

示例3:使用浮点数添加额外的空白和对齐方式更改

现在,我们将重复在上一个示例中对字符串所做的相同练习,唯一的区别是此处我们采用浮点数和不同的消息进行记录。

#!/usr/bin/env python3
name = 'root'
float_num = 95.2
## no extra padding
log = "Hey %s, the number is: %f. Cheers!" % (name, float_num)
print(log)
## added extra padding before float_num
log = "Hey %s, the number is: %10f. Cheers!" % (name, float_num)
print(log)
## ads a + sign to float_num. No whitespace added
log = "Hey %s, the number is: %+10f. Cheers!" % (name, float_num)
print(log)
## added extra padding after float_num in the right side as the text is left aligned
log = "Hey %s, the number is: %-10f. Cheers!" % (name, float_num)
print(log)
## Max 3 numbers allowed in float_num
log = "Hey %s, the number is: %.3f. Cheers!" % (name, float_num)
print(log)
## min width is 10 before float_num and max character allowed is 3 in float_num
log = "Hey %s, the number is: %10.3f. Cheers!" % (name, float_num)
print(log)

该脚本的输出:

~]# python3 string-formatting.py
Hey root, the number is: 95.200000. Cheers!
Hey root, the number is:  95.200000. Cheers!
Hey root, the number is: +95.200000. Cheers!
Hey root, the number is: 95.200000 . Cheers!
Hey root, the number is: 95.200. Cheers!
Hey root, the number is:     95.200. Cheers!

我在每个打印语句中添加了一些注释,这些注释应该可以自我解释。与我们使用字符串得到的输出相比,输出似乎有所不同。

使用string.format()进行字符串格式化

  • Python 3.x使用不同的格式设置系统,该系统比Python 2.x使用的系统更强大。

  • 现在,print语句是一个函数。

  • 格式字符串使用大括号{}创建替换字段。

  • 括号中未包含的所有内容均视为文字,并且不进行任何对话。

  • 如果需要将大括号作为文字包含在内,则可以使用'{{'和'}}来转义。

  • 此格式化系统已反向移植到Python 2.6和Python 2.7.

基本的默认格式字符串如下所示:

#!/usr/bin/env python3
name = 'hynman'
num = 4359
print('Hello {}, your roll number is {}'.format(name, num))

该脚本的输出:

~]# python3 positional-arg.py
Hello hynman, your roll number is 4359

这里的{}考虑了.format()函数提供占位符的顺序。如果我们更改.format()值的顺序:

#!/usr/bin/env python3
name = 'hynman'
num = 4359
print('Hello {}, your roll number is {}'.format(num, name))

该脚本的输出:

~]# python3 positional-arg.py
Hello 4359, your roll number is hynman

因此,输出的顺序以及.format()占位符也已更改。

为了更好地控制string.format()的工作方式,字符串格式支持两种不同类型的展示位置"

  • 位置参数:我们必须指定索引位置{index}以执行格式

  • keyword arguments:这里我们将key替换为可以用花括号{{key}中的parameter的key来访问该值的value。

位置参数

使用位置参数,我们提供大括号" {}"内的索引位置。这些占位符由基于索引位置的.format()函数中的相应值替换。就像Python列表一样,这里的索引值从第一个位置的" 0"开始。

我们将以现有示例为例,其中已更改.format()中值的顺序,但是这次我们将在{}中提供位置参数,以便将适当的值放置在模板中。

#!/usr/bin/env python3
name = 'hynman'
num = 4359
print('Hello {1}, your roll number is {0}'.format(num, name))

该脚本的输出:

~]# python3 positional-arg.py
Hello hynman, your roll number is 4359

但是,如果我们提供了.format()函数元组中不存在的索引位置,那么我们将得到IndexError

Traceback (most recent call last):
  File "positional-arg.py", line 6, in 
    print('Hello {2}, your roll number is {0}'.format(num, name))
IndexError: tuple index out of range

关键字参数

关键字参数是传递给模板的名称/值对。我们可以直接在参数中关联名称和值,因此,当我们将参数传递给模板时,就不会造成混淆。关键字参数使我们不必担心在消息模板中对参数进行正确排序,并且阐明了每个值在print语句或者模板中的作用。

在此示例中,我使用了" {name}"和" {num}"作为关键字放置位置,并且这些参数在.format()函数中定义,用于替换

#!/usr/bin/env python3
print('Hello {name}, your roll number is {num}'.format(name='hynman', num=4395))

该脚本的输出:

~]# python3 keyword-arg.py
Hello hynman, your roll number is 4395

但是,如果我们引用一个未定义的键,则将得到KeyError。在这个例子中,我用未定义的test替换了num,因此得到KeyError。

Traceback (most recent call last):
  File "keyword-arg.py", line 3, in 
    print('Hello {name}, your roll number is {test}'.format(name='hynman', num=4395))
KeyError: 'test'

使用string.format()进行高级格式化

格式相似,我们可以通过在格式字符串中添加额外的语法来获得更具体的布局。对于格式设置方法,我们在可能为空的替换目标的标识之后使用冒号,然后使用格式说明符,该说明符可以命名字段大小,对齐方式和特定的类型代码。

这是在格式字符串中可以作为替换目标出现的形式结构,它的四个部分都是"可选的",并且必须在中间插入空格:

{fieldname component !conversionflag :formatspec}

在此替换目标语法中:

  • " fieldname"是一个可选的数字或者关键字,用于标识一个参数

  • " component"是零个或者多个" .name"或者" [index]"引用的字符串,用于获取参数的属性和索引值,可以省略以使用整个参数值。

  • " conversionflag"以"!"开头(如果存在),其后是" r"," s"或者" a",以对值调用" repr"," str"或者" ascii"内置函数,分别。

  • formatspec开头(如果存在),其后是指定值显示方式的文本,包括字段宽度,对齐方式,填充,小数精度等细节,并以可选数据结尾键入代码。

以下是一些使用示例的格式说明符

说明符说明
:@@@20左对齐,宽度为20
:>20右对齐,宽度为20
:^20中心对齐,宽度为20
:06.2f浮点数精度的零填充
:*>10星号垫右对齐,宽度为10
:=10填充放在符号后面,如果有的话,放在数字前面。仅适用于数字类型
:+20在数字左边加上一个符号,宽度为20
:-20只在负数前加一个符号,左填充至20宽
:20在正数上强制一个前导空格,或者在负数上强制一个“-”,左填充到20的宽度
:,强制千位逗号表示数字
:.2%表示百分比(.975表示97.50%)
:%M/%d/%Y类型特定用法。在本例中为datetime
0:#x将整数格式化为十六进制值0xhh
0:#o将整数格式化为八进制值0oxx
0:#b将整数格式化为二进制值0bxxxxxx

示例1:使用string.format()向字符串和整数添加额外的空格填充

我们将使用高级格式化语法在此python脚本中向字符串和整数添加其他空格和填充:

该脚本的输出:

~]# python3 string-format-1.py
Hello hynman, your roll number is 43578. Best of Luck
Hello     hynman, your roll number is      43578. Best of Luck
Hello   hynman  , your roll number is   43578   . Best of Luck
Hello hynman    , your roll number is 43578     . Best of Luck
Hello hynman, your roll number is     +43578. Best of Luck
Hello hynman, your roll number is      43578. Best of Luck

我们可以检查解释输出的单个打印语句的注释。

示例2:具有浮点数的高级格式化

在此示例中,我使用了字符串和浮点数。我们在每个打印语句中添加了不同类型的对齐方式和格式。

#!/usr/bin/env python3
name = 'hynman'
num = 97.65
## no additional formatting
print('Hello {0}, you got {1} marks'.format(name, num))
## add width of 10 characters for both placeholders
print('Hello {0:10}, you got {1:10} marks'.format(name, num))
## Right align to the width of 10
print('Hello {0:>10}, you got {1:>10} marks'.format(name, num))
## Center align to the width of 10
print('Hello {0:^10}, you got {1:^10} marks'.format(name, num))
## Left align to the width of 10
print('Hello {0:<10}, you got {1:<10} marks'.format(name, num))
## Assigned a floating point format to num
print('Hello {0}, you got {1:f} marks'.format(name, num))
## truncating the floating point number to two characters after decimal for num
print('Hello {0:s}, you got {1:.2f} marks'.format(name, num))
## adds a field with a width of six characters and zero padding on the left for num
print('Hello {0:s}, you got {1:06.2f} marks'.format(name, num))

该脚本的输出:

~]# python3 string-format-2.py
Hello hynman, you got 97.65 marks
Hello hynman    , you got      97.65 marks
Hello     hynman, you got      97.65 marks
Hello   hynman  , you got   97.65    marks
Hello hynman    , you got 97.65      marks
Hello hynman, you got 97.650000 marks
Hello hynman, you got 97.65 marks
Hello hynman, you got 097.65 marks

使用f字符串进行字符串格式化

" f-strings"出现在Python 3.6中,现在是推荐的格式化字符串的方式。

  • 在引号前直接输入字母" f"或者" F"。

  • 将变量名或者表达式包括在大括号"({})"中,以将其值包含在字符串中。

就像上一节的"新样式"格式一样,但是格式格式字符串中没有format()函数,也没有空括号({})或者位置括号({1})。

这是一个简单的示例,其中我们使用关键字参数,而不是将关键字定义为变量:

#!/usr/bin/env python3
name = 'hynman'
num = 12345
print(f'Hello {name}, Your roll number is {num}')

该脚本的输出:

~]# python3 f-string-ex.py
Hello hynman, Your roll number is 12345

在所有情况下,使用f字符串格式化比使用带有%运算符和str.format方法的C样式格式字符串要短。

示例1:使用f字符串添加其他填充和对齐方式

我们可以使用与string.format()相似的语法,使用f-strings添加额外的对齐方式和填充:

#!/usr/bin/env python3
name = 'hynman'
num = 12345
## default output without any additional formatting
print(f'Hello {name}, Your roll number is {num}')
## add width of 10 characters for both placeholders
print(f'Hello {name:10}, Your roll number is {num:10}')
## Right align to the width of 10
print(f'Hello {name:>10}, Your roll number is {num:>10}')
## Center align to the width of 10
print(f'Hello {name:^10}, Your roll number is {num:^10}')
## Left align to the width of 10
print(f'Hello {name:<10}, Your roll number is {num:<10}') 
## Add asterisk to the integer and right align the content to total 10 char 
print(f'Hello {name}, Your roll number is {num:*>10}')
## Add zeroes to the integer and right align the content to total 10 char
print(f'Hello {name}, Your roll number is {num:0>10}')

该脚本的输出:

~]# python3 f-string-ex.py
Hello hynman, Your roll number is 12345
Hello hynman    , Your roll number is      12345
Hello     hynman, Your roll number is      12345
Hello   hynman  , Your roll number is   12345
Hello hynman    , Your roll number is 12345
Hello hynman, Your roll number is ** ***12345
Hello hynman    , Your roll number is 0000012345