📜  使用Python 3的f字符串进行字符串格式化

📅  最后修改于: 2020-08-26 10:40:27             🧑  作者: Mango

介绍

Python 3.6引入了一种格式化字符串的新方法:f-Strings。它比Python中其他字符串格式化方法快,并且它们使我们能够评估字符串中的Python表达式。

在本文中,我们将探讨在Python中格式化字符串的各种方法。然后,我们将更深入地研究f字符串,研究在显示不同数据时如何使用它。

Python中的传统字符串格式

在开始使用f-String之前,让我们看一下Python中可用的更多“传统” 字符串格式设置选项.

字符串串联

字符串串联意味着我们要组合两个字符串以构成一个新字符串。在Python中,我们通常将字符串与+运算符连接在一起。

在您的Python解释器中,让我们使用串联在字符串中包含一个变量: 

name = "Python"
print("I like " + name + " very much!")

您将看到以下输出: 

I like Python very much!

字符串串联仅适用于字符串。如果要包含非字符串数据,则必须手动进行转换。

让我们看一下将数字与字符串连接起来的方法:

age = (10 + 5) * 2
print("You wouldn't believe me, but I am only " + age + " years old")

运行上面的内容,您会看到此错误:

Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str

现在,让我们转换age为字符串:

age = (10 + 5) * 2
print("You wouldn't believe me, but I am only " + str(age) + " years old")

解释器将正确显示:

You wouldn't believe me, but I am only 30 years old

这种方法并非始终是Python评估最快的方法,也不是人类易于管理的带有多个变量的方法。最好使用Python专用的字符串格式化方法。

C样式字符串格式

C样式的字符串格式,也称为printf样式,使用字符串作为标有的模板,%以便可以替换变量。

例如,%d告诉Python我们正在替换数字,而%s告诉Python我们正在替换字符串。

也有一些控制机制可用,例如,%02d确保该数字至少为2位数字,如果不是,则其余数字将用零填充。我们可以使用标记%.4f来代替小数点,并在字符串中精确地使用4个浮点。

在您的Python解释器中,键入以下代码,以便我们可以看到C样式的字符串格式:

print('Here is an integer %02d' % 4)
print('And a float: %.2f' % 3.141592)
print("And a %s with %d replacements" % ("mess", 2))

您的输出应为:

Here is an integer 04
And a float: 3.14
And a mess with 2 replacements

如您所见,随着越来越多的争论,它变得非常复杂并且难以理解。因此,Python进一步迈出了这一步,并允许您在%格式化中使用字典。

尽管它在整体美学上并没有多大改善,但可以在可读性方面有所帮助。

尝试使用字典格式化C样式的字符串:

print('Using %(dictionary)s format in C-style string formatting, here is %(num)d number to make it more interesting!' % {'dictionary': "named", "num": 1})

如您所见,我们可以%在标识符和其余标识符之间的括号内指定名称。

您的口译员应显示:

Using named format in C-style string formatting, here is 1 number to make it more interesting!

如果您最近42年没有用C进行开发,那么上面的语法可能并不符合您的喜好。因此,Python使用format()字符串方法为我们提供了另一种选择。

Python format()函数

format()函数的行为类似于C样式的格式,但可读性更高。通过调用format()字符串上的方法,同时在大括号-中提供模板中的替换内容,它可以工作{}

使用您的Python解释器,我们将使用该format()方法来格式化字符串。让我们从替换一个字符串开始: 

print("This is a first {}".format("attempt!"))

输出将是: 

This is a first attempt!

我们可以多次使用花括号,按顺序替换变量: 

print("And {} can add {} string too.".format("we", "more"))

输出: 

And we can add more string too.

我们还可以命名要格式化的变量: 

print("String format also supports {dictionary} arguments.".format(dictionary="named"))

上面的代码应打印: 

String format also supports named arguments.

尽管此方法具有很高的可读性,但Python使用f-String的效率更高,同时也易于读取。让我们更仔细地研究f字符串。

用f字符串格式化字符串

F字符串或格式化的字符串文字以开头,f并包含带有花括号的替换字段。它们在运行时进行评估,这使它们成为Python中最快的字符串格式化选项(至少在标准CPython实现中)。

首先,确认您的Python版本为3.6或更高版本:

$ python3 --version
Python 3.6.0

如果您的Python版本低于3.6,则需要升级才能使用此功能。

F-String字面量以开头f,后跟任何类型的字符串(即单引号,双引号,三引号),然后可以在大括号之间的字符串中包含Python表达式。

让我们在Python shell中使用f字符串作为字符串:

name = "f-String"
print(f"hello {name}!")

现在运行它来查看魔术:

hello f-String!

这与使用该format()功能非常相似。但是,它具有许多其他格式化方法无法提供的功能。

让我们看看这些功能,从多行字符串开始。

多行f弦

F字符串允许使用多行字符串,您所要做的就是将它们用括号括起来:

name = "World"
message = (
  f"Hello {name}. "
  "This is from a multi-lined f-string. "
  f"Have a good day, {name}"
)
print(message)

您将在打印输出上看到以下内容:

Hello World. This is from a multi-lined f-string. Have a good day, World

别忘了把f文字放在有替换的行的前面。替代将无法正常工作。

评估f字符串中的Python表达式

Python的f字符串允许您直接在字符串本身中执行表达式。以下字符串有效:

number = 10
print(f"{number} + 1 = {number+1}")

并输出:

10 + 1 = 11

您可以包括任何想要的有效表达式,只要它没有特殊字符即可。例如,我们可以调用函数:

def func():
  return 42

print(f"func() = {func()}")

返回:

func() = 42

用f字符串格式化类

您可以在f字符串中包含从类创建的对象。每个类都有两种不同的方法,这些方法允许将对象转换为字符串:

  • __str__()对象的方法应返回一个既可显示给用户又可被用户理解的字符串。这意味着它不应具有任何对用户隐藏的秘密信息,并且它不应具有任何调试消息。
  • __repr__()对象的方法应返回更详细的字符串,其中可能包含调试信息。

f字符串会自动__str__()为您提供的对象调用。

让我们尝试一个带有类的f-Strings自己看看。我们将创建一个User类,该类存储虚拟系统使用的名称和关联的数据库ID。

创建一个名为的新文件,fstring_classes.py并添加以下内容:

# fstring_classes.py

class User:
    def __init__(self, name, db_id):
        self.name = name
        self.db_id = db_id

    def __str__(self):
        return f"User with name: {self.name}"

my_user = User("Sajjad", 12)
print(f"{my_user}")

在您的终端中,使用Python运行文件:

$ python fstring_classes.py

该程序将显示:

User with name: Sajjad

如果我们想将f-String与__repr_()对象的方法一起使用,则可以!r在要替换的对象前面放置一个。

编辑fstring_classes.py文件并更改最后一行:

print(f"{my_user}")

分为以下内容,包括!r后缀:

print(f"{my_user!r}")

现在我们可以再次运行该程序:

$ python fstring_classes.py

我们的输出将是:

User with name: Sajjad with id 12

处理f字符串中的特殊字符

与其他Python字符串一样,F字符串也支持使用反斜杠来转义字符。以下所有都是有效的Python f字符串:

print(f'escaping with \\ is also possible, like: \'')

运行此命令将打印:

escaping with \ is also possible, like: '

但是,有一个限制,我们不能在花括号(f-String的表达式部分)内使用反斜杠。如果您在Python解释器中尝试以下操作:

print(f'{ord("\n")}')

您将收到以下错误:

  File "", line 1
SyntaxError: f-string expression part cannot include a backslash

对于相同类型的引号,存在相同的限制。下面的代码:

a = {"key": "value"}
print(f"the value is {a["key"]}")

给我们这个语法错误:

  File "", line 1
    print(f"the value is {a["key"]}")
                               ^
SyntaxError: invalid syntax

为了避免这些问题,我们可以在f-String之外计算它们:

ord_newline = ord("\n")
print(f'{ord_newline}')

哪些打印:

10

或者我们可以使用不同的报价类型:

a = {"key": "val"}
print(f"The value is {a['key']}")

显示:

The value is val

结论

在本文中,我们研究了Python中字符串格式化的不同方法,重点是f-String方法。在Python中,由于我们可以串联字符串,使用带有C样式格式的%format()字符串的方法,因此我们对选项一无所知。

但是,使用f-Strings,我们可以获得Python进行了优化的可读解决方案。除了它的速度优势外,我们还看到了f-Strings在评估类中的表达式和对象时的表现如何。