如何在Python 3中使用字符串格式化程序

###介绍

Python 的 str.format() 方法允许您进行变量替换和值格式化。这使您能够通过位置格式化在字符串中连接元素。

本教程将指导您了解 Python 中格式化器的一些常见用法,这可以帮助使您的代码和程序更易读和用户友好。

先决条件

您应该已经安装了Python 3,并在您的计算机或服务器上设置了编程环境。如果您还没有设置编程环境,您可以参考适用于您操作系统的安装和设置指南,以设置一个适用于您的操作系统(Ubuntu、CentOS、Debian 等)的 本地编程环境 或者 服务器上的编程环境。

##使用格式化器

格式化程序通过在字符串中放置一个或多个替换字段或占位符——由一对花括号{}定义——并调用str.format()方法来工作。您将向该方法传递要与字符串连接的值。当您运行程序时,此值将通过在占位符所在的相同位置传递。

让我们打印出一个使用格式化程序的字符串:

信息:要跟随本教程中的示例代码,您可以通过运行python3命令在本地系统上打开Python交互式shell。然后,您可以通过在>>>提示后添加它们来复制、粘贴或编辑示例。

print("Sammy has {} balloons.".format(5))
Output
Sammy has 5 balloons.

在上面的示例中,我们构造了一个带有一对花括号的字符串作为占位符:

"Sammy has {} balloons."

然后,我们添加了str.format()方法,并将整数5的值传递给该方法。这将把5的值放入字符串中花括号的位置:

Sammy has 5 balloons.

我们还可以将一个变量赋值为一个具有格式化占位符的字符串的值:

open_string = "Sammy loves {}."
print(open_string.format("open source"))
Output
Sammy loves open source.

在这个第二个示例中,我们将字符串"open source"与更大的字符串连接起来,替换原始字符串中的花括号。

Python中的格式化程序允许您使用花括号作为值的占位符,您将通过str.format()方法传递这些值。

##使用带有多个占位符的格式化程序

您可以在使用格式化器时使用多对大括号。如果我们想要在上述句子中添加另一个变量替换,可以通过添加第二对大括号并将第二个值传递给方法来实现:

new_open_string = "Sammy loves {} {}."                      #2 {} 占位符
print(new_open_string.format("open-source", "software"))    #通过逗号分隔传递 2 个字符串给方法
Output
Sammy loves open-source software.

要添加另一个替换,我们在原始字符串中添加了第二对大括号。然后,我们通过逗号将两个字符串传递给 str.format() 方法。

按照相同的语法,我们可以添加额外的替换:

sammy_string = "Sammy loves {} {}, and has {} {}."                      #4 {} 占位符
print(sammy_string.format("open-source", "software", 5, "balloons"))    #通过方法传递 4 个字符串
Output
Sammy loves open-source software, and has 5 balloons.

sammy_string 中,我们添加了 4 对大括号作为变量替换的占位符。然后,我们通过 str.format() 方法传递了 4 个值,混合了字符串和整数数据类型。这些值都用逗号分隔。

##使用位置参数和关键字参数重新排列格式化器

当我们将大括号留空没有任何参数时,Python 将按顺序替换通过 str.format() 方法传递的值。正如我们所见,到目前为止,使用两个空大括号并传递两个值的格式化器构造看起来像这样:

print("Sammy the {} has a pet {}!".format("shark", "pilot fish"))
Output
Sammy the shark has a pet pilot fish!

第一对大括号将被替换为字符串值 "shark",第二对将被替换为字符串值 "pilot fish"

存在于方法中的值如下所示:

("shark", "pilot fish")

它们本质上是元组数据类型,元组中的每个单独值都可以通过其索引号进行调用,索引号从0开始。

我们可以将这些索引号传递到原始字符串中作为占位符的花括号中:

print("Sammy the {0} has a pet {1}!".format("shark", "pilot fish"))

在上面的例子中,输出将会是当我们不传递索引号到花括号中时得到的结果,因为我们按顺序调用元组中的值:

Output
Sammy the shark has a pet pilot fish!

但是,如果我们使用占位符的参数反转索引号,我们可以反转传递到字符串中的值:

print("Sammy the {1} has a pet {0}!".format("shark", "pilot fish"))
Output
Sammy the pilot fish has a pet shark!

如果你在一个只有索引位置0和1的元组中调用索引号2,那么你就是在调用超出范围的值。当你调用超出范围的索引号时,你将会收到一个错误消息:

print("Sammy the {2} has a pet {1}!".format("shark", "pilot fish"))
Output
IndexError: tuple index out of range

我们看到的错误消息是指元组仅在索引号0和1处具有值,因此将索引号2放置在超出范围之外。

让我们添加几个更多的占位符和一些更多的值传递给它们,这样我们就可以更好地理解如何重新排列格式化器。首先,这是一个带有四个占位符的新字符串:

print("Sammy is a {}, {}, and {} {}!".format("happy", "smiling", "blue", "shark"))
Output
Sammy is a happy, smiling and blue shark!

如果没有参数,传递到str.format()方法中的值将按顺序连接到字符串中。

元组中包含的字符串值对应以下索引号:

“happy” “smiling” “blue” “shark”
0 1 2 3

让我们使用值的索引号来改变它们在字符串中出现的顺序:

print("Sammy is a {3}, {2}, and {1} {0}!".format("happy", "smiling", "blue", "shark"))
Output
Sammy is a shark, blue, and smiling happy!

由于我们从索引号3开始,我们首先调用了"shark"的最后一个值。作为参数包含的其他索引号改变了原始字符串中单词出现的顺序。

除了位置参数之外,我们还可以引入关键字参数,通过它们的关键字名称调用:

print("Sammy the {0} {1} a {pr}.".format("shark", "made", pr = "pull request"))
Output
Sammy the shark made a pull request.

此示例显示了关键字参数与位置参数一起使用的情况。我们可以在位置参数旁边填写关键字参数pr,并且可以移动这些参数以改变生成的字符串:

print("Sammy the {pr} {1} a {0}.".format("shark", "made", pr = "pull request"))
Output
Sammy the pull request made a shark.

使用字符串格式化程序的位置参数和关键字参数使我们能够通过重新排序来更好地控制原始字符串。

##指定类型

我们可以在语法的大括号内包含更多参数。我们将使用格式代码语法{field_name:conversion},其中field_name指定了我们在重新排序部分中介绍的str.format()方法的参数索引号,conversion指的是您与格式化程序一起使用的数据类型的转换代码。

转换类型指的是Python使用的单字符类型代码。我们将在这里使用的代码是s表示字符串,d表示显示十进制整数(10进制),f表示我们将用于显示带有小数位的浮点数。您可以通过Python 3的官方文档了解更多关于格式规范迷你语言的信息。

让我们看一个例子,其中我们将一个整数传递给方法,但希望通过添加f转换类型参数来将其显示为浮点数:

print("Sammy ate {0:f} percent of a {1}!".format(75, "pizza"))
Output
Sammy ate 75.000000 percent of a pizza!

我们使用了{field_name:conversion}的语法来替换第一个花括号字段,以输出一个浮点数。第二个花括号只使用了第一个参数{field_name}

在上面的例子中,小数点后显示了很多数字,但您可以限制这些数字。当您为浮点数值指定f时,您可以通过在点.后面加上您想要包含的小数位数来另外指定该值的精度。

如果Sammy吃了75.765367%的比萨,但我们不需要高度精确,我们可以通过在转换类型f之前添加.3来将小数点后的位数限制为3:

print("Sammy ate {0:.3f} percent of a pizza!".format(75.765367))
Output
Sammy ate 75.765 percent of a pizza!

如果我们只想要一位小数点,我们可以像这样重写字符串和方法:

print("Sammy ate {0:.1f} percent of a pizza!".format(75.765367))
Output
Sammy ate 75.8 percent of a pizza!

请注意,修改精度会导致数字被四舍五入。

虽然我们将没有小数位的数字显示为浮点数,但如果我们尝试使用d转换类型将浮点数更改为整数,我们将收到一个错误:

print("Sammy ate {0:d} percent of a pizza!".format(75.765367))
Output
ValueError: Unknown format code 'd' for object of type 'float'

如果您希望不显示小数位,可以这样编写格式化程序:

print("Sammy ate {0:.0f} percent of a pizza!".format(75.765367))
Output
Sammy ate 76 percent of a pizza!

这不会将您的浮点数转换为整数,而是限制小数点后显示的位数。

##填充变量替换

由于占位符是替换字段,因此可以通过增加额外的参数来填充或在元素周围创建空间。当我们需要在视觉上整理大量数据时,这可能很有用。

我们可以在大括号语法的冒号:之后添加一个数字来指示字段大小(以字符为单位):

print("Sammy has {0:4} red {1:16}!".format(5, "balloons"))
Output
Sammy has 5 red balloons !

在上面的示例中,我们将数字5的字符字段大小设置为4,将字符串balloons的字符字段大小设置为16(因为它是一个长字符串)。

如我们所见,默认情况下,字符串在字段内左对齐,数字右对齐。您可以通过在冒号后面放置对齐代码来修改此设置。<将文本左对齐在字段中,^将文本居中显示在字段中,>将文本右对齐。

让我们将数字左对齐,并将字符串居中显示:

print("Sammy has {0:<4} red {1:^16}!".format(5, "balloons"))
Output
Sammy has 5 red balloons !

现在我们看到5被左对齐,在red之前提供了字段空间,balloons在其字段中居中显示,两侧有空间。

默认情况下,当我们使用格式化程序扩大字段时,Python将使用空白字符填充字段。我们可以通过在冒号后直接指定要使用的字符来修改为不同的字符:

print("{:*^20s}".format("Sammy"))
Output
*******Sammy********

我们接受传递给str.format()的字符串,索引位置为0,因为我们没有另行指定,包括冒号,并指定我们将使用*而不是空格来填充字段。我们使用^将字符串居中,指定字段大小为20个字符,并指示我们正在使用字符串转换类型,包括s

我们可以将这些参数与以前使用过的其他参数组合使用:

print("Sammy ate {0:5.0f} percent of a pizza!".format(75.765367))
Output
Sammy ate 76 percent of a pizza!

在大括号内的参数中,我们指定了浮点数的索引字段编号并包括冒号,指定了字段数字的大小并包括句点,写入了小数点后的位数,然后指定了f的转换类型。

##使用变量

到目前为止,我们已经将整数、浮点数和字符串传递给了str.format()方法,但是我们也可以通过该方法传递变量。这与任何其他变量的工作方式相同。

nBalloons = 8
print("Sammy has {} balloons today!".format(nBalloons))
Output
Sammy has 8 balloons today!

我们可以为原始字符串和传递给该方法的内容都使用变量:

sammy = "Sammy has {} balloons today!"
nBalloons = 8
print(sammy.format(nBalloons))
Output
Sammy has 8 balloons today!

变量可以很容易地替换我们格式化语法结构的每个部分。当我们接受用户生成的输入并将这些值分配给变量时,这样做会更容易。

##使用格式化器组织数据

当格式化器被用于以视觉方式组织大量数据时,它们可以发挥最佳作用。如果我们向用户显示数据库,则使用格式化器来增加字段大小并修改对齐方式可以使您的输出更易读。

让我们来看一个典型的Python中的for循环,它将在范围从3到12的情况下打印出ii*ii*i*i

for i in range(3,13):
    print(i, i*i, i*i*i)
Output
3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 11 121 1331 12 144 1728

虽然输出已经以一种方式组织起来,但数字溢出到彼此的列中,使得输出底部不太可读。如果您正在处理一个具有许多小数字和大数字的更大数据集,这可能会成为一个问题。

让我们使用格式化器给这些数字更多的空间:

for i in range(3,13):
    print("{:3d} {:4d} {:5d}".format(i, i*i, i*i*i))

在这里,在我们的花括号中,我们没有为索引号添加字段名称,而是以冒号开头,后跟字段大小的数字,以及d转换类型,因为我们正在处理整数。在这个例子中,我们为每个预期输出的大小做了适应,为每个额外给了2个字符空间,具体取决于最大可能的数字大小,所以我们的输出看起来像这样:

Output
3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 11 121 1331 12 144 1728

我们可以指定一个一致的字段大小数字,以便拥有均匀的列,确保我们可以容纳更大的数字:

for i in range(3,13):
    print("{:6d} {:6d} {:6d}".format(i, i*i, i*i*i))
Output
3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 11 121 1331 12 144 1728

我们还可以通过添加<^>来操纵列的对齐方式,将d改为f以增加小数位数,更改字段名称索引号等,以确保我们显示的数据符合我们的期望。

##结论

使用变量替换的格式化器可以是连接字符串和组织值和数据的有效方式。格式化器代表一种基本但非描述性的方式,用于将变量替换传递到字符串中,并且对于确保输出可读性和用户友好性非常有用。

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-string-formatters-in-python-3