Python 的格式化字符串(f-string,格式化字符串字面量)是 Python 3.6 引入的一种强大且简洁的字符串格式化工具,通过在字符串前添加 f
或 F
前缀,并使用花括号 {}
嵌入变量或表达式,实现动态字符串生成。本文将详细介绍 f-string 的定义、语法、用法、格式化选项、版本改进、性能、适用场景、注意事项及最佳实践。
f-string 是 Python 3.6 及以上版本支持的字符串格式化方法,由 PEP 498 – Literal String Interpolation 提出,旨在提供比传统 %
格式化、str.format()
和 string.Template
更简洁、可读且高效的方式。f-string 允许在字符串字面量中直接嵌入 Python 表达式,运行时动态求值。
核心特点:
f"文本 {表达式}"
嵌入变量或表达式。=
修饰符,便于调试。示例:
name = "Alice"
age = 25
print(f"姓名: {name}, 年龄: {age}") # 输出: 姓名: Alice, 年龄: 25
与元类的关系:虽然 f-string 本身不直接涉及元类,但其实现依赖 Python 的动态求值机制,表达式在运行时通过 eval()
解析,类似于元类在类创建时的动态干预。
f-string 的语法为在字符串前添加 f
或 F
,在字符串中使用 {表达式}
嵌入内容,表达式在运行时求值。
f-string 支持嵌入变量、常量、算术运算、函数调用等。
示例:
x = 10
y = 20
print(f"结果: {x + y}") # 输出: 结果: 30
print(f"平方: {x ** 2}") # 输出: 平方: 100
def greet(name):
return f"你好, {name}!"
print(greet("Bob")) # 输出: 你好, Bob!
f-string 支持列表推导式、字典操作等复杂表达式。
示例:
names = ["Alice", "Bob", "Charlie"]
print(f"名字: {', '.join(name.upper() for name in names)}") # 输出: 名字: ALICE, BOB, CHARLIE
data = {"a": 1, "b": 2}
print(f"键值对: {list(data.items())}") # 输出: 键值对: [('a', 1), ('b', 2)]
f-string 支持多行字符串,适合复杂格式化。
示例:
name = "Alice"
age = 25
print(f"""
个人信息:
姓名: {name}
年龄: {age}
""")
# 输出:
# 个人信息:
# 姓名: Alice
# 年龄: 25
f-string 使用格式说明符(format specification mini-language)控制输出格式,语法为 {表达式:格式说明符}
,格式说明符位于 :
之后。格式说明符支持填充、对齐、宽度、精度和类型等,基于 Python 官方文档:Common String Operations。
格式说明符 ::= [[填充]对齐][符号]["z"]["#"]["0"][宽度][分组]["." 精度][类型]
_
、*
)。<
(左对齐)、>
(右对齐)、^
(居中)。+
(显示正负号)、-
(仅负号)、空格(正数前加空格)。0x
前缀)。,
或 _
)。s
(字符串)、d
(十进制)、f
(浮点数)、x
(十六进制)。对齐和填充:
name = "Bob"
print(f"{name:>10}") # 输出: " Bob"(右对齐,宽度10)
print(f"{name:_<10}") # 输出: "Bob_______"(左对齐,用_填充)
print(f"{name:*^10}") # 输出: "***Bob****"(居中,用*填充)
数字格式化:
pi = 3.14159
print(f"Pi: {pi:.2f}") # 输出: Pi: 3.14(2位小数)
print(f"Pi: {pi:,.2f}") # 输出: Pi: 3,141.59(千位分隔)
num = 42
print(f"Number: {num:05d}") # 输出: Number: 00042(零填充)
print(f"Hex: {num:#x}") # 输出: Hex: 0x2a(十六进制带前缀)
其他类型:
from datetime import datetime
now = datetime.now()
print(f"日期: {now:%Y-%m-%d}") # 输出: 日期: 2025-05-18
表 1:常见格式说明符
表达式 | 输出 | 说明 |
---|---|---|
f"{pi:.2f}" |
3.14 | 浮点数,2位小数 |
f"{num:>10d}" |
" 42" | 右对齐,宽度10 |
f"{pi:,.2f}" |
3,141.59 | 千位分隔,2位小数 |
f"{num:+d}" |
+42 | 带符号的十进制 |
f"{num:05d}" |
00042 | 零填充,宽度5 |
f"{num:#x}" |
0x2a | 十六进制,带前缀 |
f-string 支持修饰符 !s
、!r
和 !a
,分别调用 str()
、repr()
和 ascii()
,用于控制表达式输出形式。
示例:
class Person:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Person: {self.name}"
def __repr__(self):
return f"Person(name='{self.name}')"
p = Person("Charlie")
print(f"{p!s}") # 输出: Person: Charlie
print(f"{p!r}") # 输出: Person(name='Charlie')
print(f"{p!a}") # 输出: Person(name='Charlie')(ASCII 编码)
调试模式(Python 3.8+):
使用 =
修饰符显示表达式及其值,便于调试。
示例:
x = 10
y = 20
print(f"{x=}, {y=}, {x + y=}") # 输出: x=10, y=20, x + y=30
根据 What’s New In Python 3.12 和 PEP 701,Python 3.12 放宽了 f-string 的语法限制,提升灵活性:
\n
)。示例:
words = ["hello", "world"]
print(f"{'\\n'.join(words)}") # 输出: hello\nworld
# 嵌套引号
print(f"{'\"quoted\"'}") # 输出: "quoted"
# 多行表达式
print(f"""
结果: {
# 计算总和
sum([1, 2, 3])
}
""") # 输出: 结果: 6
这些改进使 f-string 在复杂场景下更易用,研究显示其在多行格式化和动态生成中效果显著。
f-string 在性能上优于传统格式化方法,因其在编译时解析为字节码,减少运行时开销。根据 Real Python 的基准测试(Real Python: Python’s F-String),在 1,000,000 次迭代中:
原因:
str.format()
的参数解析。示例性能测试:
import timeit
print(timeit.timeit('f"Number: {42}"', number=1000000)) # 更快
print(timeit.timeit('"Number: %d" % 42', number=1000000)) # 稍慢
print(timeit.timeit('"Number: {}".format(42)', number=1000000)) # 最慢
f-string 适用于大多数字符串格式化场景,包括:
score = 95
print(f"你的得分是: {score}/100") # 输出: 你的得分是: 95/100
user = "Alice"
print(f"用户 {user} 已登录")
from datetime import datetime
now = datetime.now()
print(f"当前时间: {now:%Y-%m-%d %H:%M:%S}") # 输出: 当前时间: 2025-05-18 09:49:00
=
修饰符检查变量值。x = 42
print(f"{x=}") # 输出: x=42
尽管 f-string 功能强大,但需注意以下事项:
版本兼容性:
SyntaxError
。=
修饰符)需 3.8+,反斜杠支持需 3.12+。日志记录:
logging
模块的 %
格式化,延迟求值。import logging
logging.warning("用户 %s 已登录", "Alice") # 优于 f-string
安全性:
user_input = ".__class__.__bases__[0].__subclasses__()"
# 危险: print(f"{eval(user_input)}")
cursor.execute("SELECT * FROM users WHERE name = ?", (name,))
可读性:
# 不可读
print(f"结果: {sum([x * y for x in range(10) for y in range(10)])}")
# 改进
total = sum(x * y for x in range(10) for y in range(10))
print(f"结果: {total}")
国际化:
str.format()
或模板。template = "姓名: {name}, 年龄: {age}"
print(template.format(name="Alice", age=25))
保持简洁:
# 推荐
result = x + y
print(f"结果: {result}")
# 避免
print(f"结果: {x + y + complex_calculation()}")
使用格式化选项:
print(f"{'项目':<10} {'得分':>5}")
print(f"{'数学':<10} {95:>5}")
# 输出:
# 项目 得分
# 数学 95
调试优先:
=
修饰符快速检查变量值。print(f"{data['key']=}") # 检查字典值
性能优化:
for i in range(1000):
print(f"迭代: {i}") # 优于 str.format()
安全性检查:
name = sanitize_input(user_input)
print(f"欢迎, {name}")
功能 | 示例 | 说明 |
---|---|---|
基本嵌入 | f"姓名: {name}" |
嵌入变量或简单表达式 |
复杂表达式 | f"{', '.join(names)}" |
支持推导式、函数调用 |
格式化对齐 | f"{name:>10}" |
控制宽度、填充、左右居中 |
数字格式化 | f"{pi:.2f}" |
控制精度、千位分隔、符号 |
修饰符 | f"{obj!r}" |
调用 str()、repr()、ascii() |
调试模式 | f"{x=}" |
显示表达式和值(3.8+) |
多行和注释 | f"结果: {sum([1, 2]) # 注释}" |
支持反斜杠、注释(3.12+) |
f-string 是 Python 中最现代、最推荐的字符串格式化工具,凭借简洁的语法、高效的性能和丰富的格式化选项,广泛应用于文本输出、数据格式化、调试等领域。Python 3.8 和 3.12 的改进进一步增强了其功能,但需注意日志记录、安全性和版本兼容性。学习者应通过实践掌握 f-string 的核心用法和最佳实践,结合格式化选项提升代码质量。