> 技术文档 > 【Python】Python 的格式化字符串(f-string)_python f-string

【Python】Python 的格式化字符串(f-string)_python f-string

Python 的格式化字符串(f-string,格式化字符串字面量)是 Python 3.6 引入的一种强大且简洁的字符串格式化工具,通过在字符串前添加 fF 前缀,并使用花括号 {} 嵌入变量或表达式,实现动态字符串生成。本文将详细介绍 f-string 的定义、语法、用法、格式化选项、版本改进、性能、适用场景、注意事项及最佳实践。


1. 什么是 f-string?

f-string 是 Python 3.6 及以上版本支持的字符串格式化方法,由 PEP 498 – Literal String Interpolation 提出,旨在提供比传统 % 格式化、str.format()string.Template 更简洁、可读且高效的方式。f-string 允许在字符串字面量中直接嵌入 Python 表达式,运行时动态求值。

核心特点:

  • 简洁语法:通过 f\"文本 {表达式}\" 嵌入变量或表达式。
  • 高效性能:编译时解析为字节码,执行速度快。
  • 灵活性:支持任意 Python 表达式,包括运算 复杂运算、函数调用和推导式。
  • 格式化选项:支持对齐、精度、类型等格式控制。
  • 调试支持:Python 3.8+ 提供 = 修饰符,便于调试。

示例:

name = \"Alice\"age = 25print(f\"姓名: {name}, 年龄: {age}\") # 输出: 姓名: Alice, 年龄: 25

与元类的关系:虽然 f-string 本身不直接涉及元类,但其实现依赖 Python 的动态求值机制,表达式在运行时通过 eval() 解析,类似于元类在类创建时的动态干预。


2. f-string 的基本语法和用法

f-string 的语法为在字符串前添加 fF,在字符串中使用 {表达式} 嵌入内容,表达式在运行时求值。

2.1 基本用法

f-string 支持嵌入变量、常量、算术运算、函数调用等。

示例:

x = 10y = 20print(f\"结果: {x + y}\") # 输出: 结果: 30print(f\"平方: {x ** 2}\") # 输出: 平方: 100def greet(name): return f\"你好, {name}!\"print(greet(\"Bob\")) # 输出: 你好, Bob!

2.2 复杂表达式

f-string 支持列表推导式、字典操作等复杂表达式。

示例:

names = [\"Alice\", \"Bob\", \"Charlie\"]print(f\"名字: {\', \'.join(name.upper() for name in names)}\") # 输出: 名字: ALICE, BOB, CHARLIEdata = {\"a\": 1, \"b\": 2}print(f\"键值对: {list(data.items())}\") # 输出: 键值对: [(\'a\', 1), (\'b\', 2)]

2.3 多行 f-string

f-string 支持多行字符串,适合复杂格式化。

示例:

name = \"Alice\"age = 25print(f\"\"\"个人信息: 姓名: {name} 年龄: {age}\"\"\")# 输出:# 个人信息:# 姓名: Alice# 年龄: 25

3. 格式化选项

f-string 使用格式说明符(format specification mini-language)控制输出格式,语法为 {表达式:格式说明符},格式说明符位于 : 之后。格式说明符支持填充、对齐、宽度、精度和类型等,基于 Python 官方文档:Common String Operations。

3.1 格式说明符语法

格式说明符 ::= [[填充]对齐][符号][\"z\"][\"#\"][\"0\"][宽度][分组][\".\" 精度][类型]
  • 填充:任意字符,用于填充空白(如 _*)。
  • 对齐<(左对齐)、>(右对齐)、^(居中)。
  • 符号+(显示正负号)、-(仅负号)、空格(正数前加空格)。
  • z:将负零转为正零(Python 3.11+)。
  • #:备用格式(如为十六进制加 0x 前缀)。
  • 0:数字左填充零。
  • 宽度:输出最小宽度。
  • 分组:千位分隔符(,_)。
  • 精度:小数点后位数或字符串最大长度。
  • 类型:如 s(字符串)、d(十进制)、f(浮点数)、x(十六进制)。

3.2 常见格式化示例

对齐和填充:

name = \"Bob\"print(f\"{name:>10}\") # 输出: \" Bob\"(右对齐,宽度10)print(f\"{name:_<10}\") # 输出: \"Bob_______\"(左对齐,用_填充)print(f\"{name:*^10}\") # 输出: \"***Bob****\"(居中,用*填充)

数字格式化:

pi = 3.14159print(f\"Pi: {pi:.2f}\") # 输出: Pi: 3.14(2位小数)print(f\"Pi: {pi:,.2f}\") # 输出: Pi: 3,141.59(千位分隔)num = 42print(f\"Number: {num:05d}\") # 输出: Number: 00042(零填充)print(f\"Hex: {num:#x}\") # 输出: Hex: 0x2a(十六进制带前缀)

其他类型:

from datetime import datetimenow = 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 十六进制,带前缀

4. 修饰符与调试

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: Charlieprint(f\"{p!r}\") # 输出: Person(name=\'Charlie\')print(f\"{p!a}\") # 输出: Person(name=\'Charlie\')(ASCII 编码)

调试模式(Python 3.8+)
使用 = 修饰符显示表达式及其值,便于调试。

示例:

x = 10y = 20print(f\"{x=}, {y=}, {x + y=}\") # 输出: x=10, y=20, x + y=30

5. Python 3.12 的改进

根据 What’s New In Python 3.12 和 PEP 701,Python 3.12 放宽了 f-string 的语法限制,提升灵活性:

  • 支持反斜杠:允许在表达式中使用反斜杠(如 \\n)。
  • 重复引号:允许嵌套与 f-string 相同的引号。
  • 注释和多行表达式:支持在表达式中添加注释和多行代码。

示例:

words = [\"hello\", \"world\"]print(f\"{\'\\\\n\'.join(words)}\") # 输出: hello\\nworld# 嵌套引号print(f\"{\'\\\"quoted\\\"\'}\") # 输出: \"quoted\"# 多行表达式print(f\"\"\"结果: { # 计算总和 sum([1, 2, 3])}\"\"\") # 输出: 结果: 6

这些改进使 f-string 在复杂场景下更易用,研究显示其在多行格式化和动态生成中效果显著。


6. 性能比较

f-string 在性能上优于传统格式化方法,因其在编译时解析为字节码,减少运行时开销。根据 Real Python 的基准测试(Real Python: Python’s F-String),在 1,000,000 次迭代中:

  • f-string:87.08 ms
  • % 运算符:90.98 ms
  • str.format():144.69 ms

原因

  • f-string 直接嵌入表达式,避免了 str.format() 的参数解析。
  • 编译时优化,表达式求值更高效。

示例性能测试:

import timeitprint(timeit.timeit(\'f\"Number: {42}\"\', number=1000000)) # 更快print(timeit.timeit(\'\"Number: %d\" % 42\', number=1000000)) # 稍慢print(timeit.timeit(\'\"Number: {}\".format(42)\', number=1000000)) # 最慢

7. 适用场景

f-string 适用于大多数字符串格式化场景,包括:

  • 用户输出:生成格式化的用户界面文本。
    score = 95print(f\"你的得分是: {score}/100\") # 输出: 你的得分是: 95/100
  • 日志消息:快速构造日志字符串(但见注意事项)。
    user = \"Alice\"print(f\"用户 {user} 已登录\")
  • 数据格式化:处理数字、日期等。
    from datetime import datetimenow = datetime.now()print(f\"当前时间: {now:%Y-%m-%d %H:%M:%S}\") # 输出: 当前时间: 2025-05-18 09:49:00
  • 调试:使用 = 修饰符检查变量值。
    x = 42print(f\"{x=}\") # 输出: x=42

8. 注意事项

尽管 f-string 功能强大,但需注意以下事项:

  1. 版本兼容性

    • f-string 仅在 Python 3.6+ 可用,旧版本会抛出 SyntaxError
    • 某些功能(如 = 修饰符)需 3.8+,反斜杠支持需 3.12+。
  2. 日志记录

    • f-string 立即求值,可能在日志未记录时浪费资源。
    • 推荐:使用 logging 模块的 % 格式化,延迟求值。
      import logginglogging.warning(\"用户 %s 已登录\", \"Alice\") # 优于 f-string
  3. 安全性

    • 避免将用户输入直接嵌入表达式,可能导致代码注入。
      user_input = \".__class__.__bases__[0].__subclasses__()\"# 危险: print(f\"{eval(user_input)}\")
    • 对于 SQL 查询,使用参数化查询而非 f-string:
      cursor.execute(\"SELECT * FROM users WHERE name = ?\", (name,))
  4. 可读性

    • 复杂表达式可能降低可读性,建议拆分为多行或预计算。
      # 不可读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}\")
  5. 国际化

    • f-string 不直接支持动态格式化,国际化场景可能需 str.format() 或模板。
      template = \"姓名: {name}, 年龄: {age}\"print(template.format(name=\"Alice\", age=25))

9. 最佳实践

  1. 保持简洁

    • 使用简单表达式,避免嵌套复杂逻辑。
    • 示例:
      # 推荐result = x + yprint(f\"结果: {result}\")# 避免print(f\"结果: {x + y + complex_calculation()}\")
  2. 使用格式化选项

    • 充分利用对齐、精度等功能,提升输出美观性。
      print(f\"{\'项目\':<10} {\'得分\':>5}\")print(f\"{\'数学\':<10} {95:>5}\")# 输出:# 项目 得分# 数学 95
  3. 调试优先

    • 使用 = 修饰符快速检查变量值。
      print(f\"{data[\'key\']=}\") # 检查字典值
  4. 性能优化

    • 在循环中优先使用 f-string,减少格式化开销。
      for i in range(1000): print(f\"迭代: {i}\") # 优于 str.format()
  5. 安全性检查

    • 对用户输入进行清洗,必要时使用参数化或模板。
      name = sanitize_input(user_input)print(f\"欢迎, {name}\")

10. 总结表

功能 示例 说明 基本嵌入 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+)

11. 学习资源

  • 官方文档
    • Python 教程:输入和输出
    • Common String Operations
    • What’s New In Python 3.12
  • 教程
    • Real Python:Python’s F-String for String Interpolation and Formatting
    • W3Schools:Python F-Strings
  • 规范
    • PEP 498 – Literal String Interpolation
    • PEP 701 – Syntactic Formalization of f-strings
  • 书籍
    • 《Fluent Python》:深入讲解字符串处理。
    • 《Python Cookbook》:f-string 实用案例。

12. 总结

f-string 是 Python 中最现代、最推荐的字符串格式化工具,凭借简洁的语法、高效的性能和丰富的格式化选项,广泛应用于文本输出、数据格式化、调试等地方。Python 3.8 和 3.12 的改进进一步增强了其功能,但需注意日志记录、安全性和版本兼容性。学习者应通过实践掌握 f-string 的核心用法和最佳实践,结合格式化选项提升代码质量。