Python 3.6 引入了新的字符串格式化方式 f-strings,与其它格式化方式相比,不仅简洁明了,可读性更好,更不容易出错,而且运行效率也更高。
你应该马上开始使用这种新的格式化方式,本文将解释其原因与具体用法。
但在此之前,让我们先看一下 f-strings 之前的字符串格式化方式。
1. Python 字符串格式化的“旧式”做法
在 Python 3.6 之前,把 Python 表达式嵌入字符串,主要有两种方式:% 或 str.format()。它们的用法与主要不足如下:
1.1 选项1:使用 %
这是最原始的、 Python 官方指南所用的格式化方式,相关信息可以阅读官方文档。
值得注意的是,官方文档其实并不推荐使用这种方式,相关说明如下:
“此处描述的格式化操作存在一些奇怪之处,容易导致一些常见错误(比如无法正确格式化元组与字典等)。
使用新的格式化方式或str.format()函数可以避免这些错误。这些格式化方式不仅更强大,而且更灵活,更易于扩展。(来源)
如何使用 % 进行格式化
字符串对象有一个内建操作符%,可以用于格式化操作,具体用法如下:
>>> name = "Eric" >>> "Hello, %s." % name 'Hello, Eric.'
如果要在字符串中嵌入多个变量,则必须使用元组,例如:
>>> name = "Eric">>> age = 74 >>> "Hello, %s. You are %s." % (name, age) 'Hello Eric. You are 74.'
% 格式化的问题
上面的代码看起来还不错,但如果在更长的字符串中嵌入更多变量,代码的可读性就会成为一个问题:
>>> first_name = "Eric" >>> last_name = "Idle" >>> age = 74 >>> profession = "comedian" >>> affiliation = "Monty Python" >>> "Hello, %s %s. You are %s. You are a %s. You were a member of %s." % (first_name, last_name, age, profession, affiliation) 'Hello, Eric Idle. You are 74. You are a comedian. You were a member of Monty Python.'
因此,这种格式化方式的主要问题是过于繁琐,容易出错,不能正确格式化元组与字典。
1.2 选项2:str.format()
这种方式是在 Python 2.6 引入的,可以在 官方文档 找到相关介绍。
str.format() 的用法
str.format()方式是对 % 方式的一次改进。用户可以通过修改对象的 __format__() 方法来自定义 格式化方式 。
通过大括号,我们可以在字符串中嵌入变量:
>>> "Hello, {}. You are {}.".format(name, age) 'Hello, Eric. You are 74.'
也可以指定变量的引用顺序:
>>> "Hello, {1}. You are {0}.".format(age, name) 'Hello, Eric. You are 74.'
或者直接使用变量名称:
>>> person = {'name': 'Eric', 'age': 74} >>> "Hello, {name}. You are {age}.".format(name=person['name'], age=person['age']) 'Hello, Eric. You are 74.'
在引用字典时,可以用**操作符进行字典拆包:
>>> person = {'name': 'Eric', 'age': 74} >>> "Hello, {name}. You are {age}.".format(**person) 'Hello, Eric. You are 74.'
总的来说,str.format()是 % 格式化方式的一次升级,但依然存在一些问题。
str.format() 的问题
和 % 方式相比,使用str.format() 的代码可读性要好很多。但如果在较长的字符串中嵌入多个变量,依然会显得繁琐:
>>> first_name = "Eric" >>> last_name = "Idle" >>> age = 74 >>> profession = "comedian" >>> affiliation = "Monty Python" >>> print(("Hello, {first_name} {last_name}. You are {age}. " + >>> "You are a {profession}. You were a member of {affiliation}.") >>> .format(first_name=first_name, last_name=last_name, age=age, >>> profession=profession, affiliation=affiliation)) 'Hello, Eric Idle. You are 74. You are a comedian. You were a member of Monty Python.'
当然,如果我们提前把需要嵌入的变量放在一个字典中,就可以通过 ** 进行拆包操作,从而显得简洁一些。
但一定还存在着更好的格式化方式。
2. f-Strings:一种改进版格式化方式
Python 3.6 引入了新的字符串格式化方式,这种方式来自于 Eric V. Smith 在 2015 年 8 月提出的方案,具体可以参考PEP 498。
f-strings 也称作“格式化的字符串字面量”,它是一个带有 f 前缀的字符串,通过大括号嵌入所需的 Python 表达式,这些表达式的具体值是在运行时确定的,背后依赖的也是嵌入对象的 __format()__ 接口。查看 官方文档 可以获得更多信息。
以下是一些具体使用方式:
2.1 最简单的句法
f-strings 的句法类似于str.format(),但要更简洁,你可以感受一下它的可读性:
>>> name = "Eric" >>> age = 74 >>> f"Hello, {name}. You are {age}." 'Hello, Eric. You are 74.'
前缀f也可以使用大写的F。
>>> F"Hello, {name}. You are {age}." 'Hello, Eric. You are 74.'
你是不是已经开始喜欢上这种格式化方式了?
2.2 支持任意表达式
由于 f-strings 是在运行时计算具体值的,我们得以在字符串中嵌入任意有效的 Python 表达式,从而写出更优雅的代码。
你可以使用很直接的计算式,比如说:
>>> f"{2 * 37}" '74'
也可以在里面调用函数:
>>> def to_lowercase(input): ... return input.lower() >>> name = "Eric Idle" >>> f"{to_lowercase(name)} is funny." 'eric idle is funny.'
或者直接调用对象的方法:
>>> f"{name.lower()} is funny." 'eric idle is funny.'
甚至可以在对象的字符串方法中直接使用 f-strings,例如有以下类:
class Comedian: def __init__(self, first_name, last_name, age): self.first_name = first_name self.last_name = last_name self.age = age def __str__(self): return f"{self.first_name} {self.last_name} is {self.age}." def __repr__(self): return f"{self.first_name} {self.last_name} is {self.age}. Surprise!"
你可以有如下代码:
>>> new_comedian = Comedian("Eric