飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • 第1章 Python简介

    • Python是什么
    • 安装与运行
    • 交互式解释器
    • 注释与编码规范
  • 第2章 变量与数据类型

    • 变量与对象
    • 整数 int
    • 浮点数 float
    • 复数 complex
    • 布尔值 bool
    • 字符串 str
    • 空值 None
    • 类型转换
  • 第3章 运算符与表达式

    • 算术运算符
    • 比较运算符
    • 赋值运算符
    • 逻辑运算符
    • 位运算符
    • 身份与成员运算符
    • 海象运算符
    • 运算符优先级
  • 第4章 流程控制

    • if 语句
    • if-else 语句
    • if-elif-else 语句
    • match-case 语句
    • 条件表达式(三元运算符)
    • while 循环
    • for 循环
    • range 函数
    • break 与 continue
    • 循环的 else 子句
    • pass 语句
  • 第5章 数据结构

    • 列表创建与索引
    • 列表方法
    • 列表推导式
    • 元组
    • 序列解包
    • 集合
    • 字典创建与访问
    • 字典方法
    • 字典推导式
    • range 对象
  • 第6章 函数

    • 定义函数
    • 位置参数与关键字参数
    • 默认参数
    • 可变参数
    • 解包实参
    • 函数返回值
    • lambda 表达式
    • 文档字符串与注解
    • 作用域与命名空间
    • global 与 nonlocal
  • 第7章 模块与包

    • 模块导入
    • 模块搜索路径
    • 包与相对导入
    • 标准库概览
  • 第8章 文件与输入输出

    • 文件读写
    • 上下文管理器
    • 字符串格式化
    • JSON 与 CSV
  • 第9章 面向对象

    • 类与对象
    • 方法
    • 实例变量与类变量
    • 私有变量
    • 继承
    • 多重继承
    • 魔术方法
    • 属性装饰器
    • 数据类 dataclass
  • 第10章 异常处理

    • 语法错误与异常
    • try-except
    • 异常链与 raise
    • 清理操作
    • 自定义异常
  • 第11章 迭代器与生成器

    • 迭代器协议
    • 生成器
    • 生成器表达式
    • 迭代工具
  • 第12章 高级特性

    • 装饰器
    • 函数式编程
  • 第13章 工程实践

    • 测试与调试
    • 代码质量
    • 虚拟环境

字符串格式化

将数据嵌入字符串是编程中最频繁的操作之一。Python 提供了三条技术路线:旧式的 % 运算符、面向对象的 str.format() 方法,以及 Python 3.6 起成为首选的 f-string(格式化字符串字面值)。三者底层共享同一套格式规范迷你语言,但 f-string 在可读性和执行效率上全面领先。

旧式 % 格式化

% 运算符模拟 C 语言的 printf 风格,左侧是含转换说明符的模板字符串,右侧是要插入的值(单个对象或元组)。

import math
print('The value of pi is approximately %5.3f.' % math.pi)
# The value of pi is approximately 3.142.

常用转换说明符:

  • %s —— 调用 str() 转换。
  • %r —— 调用 repr() 转换。
  • %d / %i —— 有符号十进制整数。
  • %f —— 浮点数,默认 6 位小数;%5.3f 表示总宽度 5、小数 3 位。
  • %x / %X —— 十六进制。
  • %% —— 字面百分号。

右侧为多个值时必须用元组包裹,字典则配合 %(name)s 语法:

data = {'name': 'Alice', 'score': 92}
print('%(name)s got %(score)d points' % data)

% 格式化在 Python 3 中仍可用,但官方文档已将其标记为旧式方法。其缺陷在于:类型匹配不严格(传错类型可能静默失败或输出意外结果)、元组单元素时的逗号陷阱、以及可读性较差。新项目应优先使用 f-string。

str.format() 方法

str.format() 使用花括号 {} 作为占位符,支持位置索引、关键字名称、甚至属性访问和元素索引,表达能力远超 %。

# 位置参数
print('{0} and {1}'.format('spam', 'eggs'))   # spam and eggs
print('{1} and {0}'.format('spam', 'eggs'))   # eggs and spam

# 关键字参数
print('This {food} is {adjective}.'.format(
    food='spam', adjective='absolutely horrible'))

# 混合使用
print('The story of {0}, {1}, and {other}.'.format(
    'Bill', 'Manfred', other='Georg'))

当格式字符串较长时,直接传入字典并用方括号访问键,或更优雅地用 ** 解包字典,可避免冗长的位置编号:

table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}

# 方括号访问
print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}'.format(table))

# ** 解包,字段名直接对应键名
print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))

与 vars() 配合,可以一键格式化当前作用域的所有局部变量,在调试日志中极为实用:

x = 10
y = 20
print('x={x}, y={y}'.format(**vars()))   # x=10, y=20

str.format() 的真正威力在于格式规范。花括号内冒号后的部分遵循与 f-string 相同的迷你语言,例如 {0:2d} {1:3d} {2:4d} 可生成整齐的数据列。

f-string:首选方案

在字符串引号前加 f 或 F,即可在 {} 中直接嵌入任意 Python 表达式。表达式在运行时被求值,结果按格式说明格式化后插入字符串。

year = 2016
event = 'Referendum'
print(f'Results of the {year} {event}')
# Results of the 2016 Referendum

f-string 支持完整的表达式,不限于变量名:

import math
r = 5
print(f'Area = {math.pi * r ** 2:.2f}')   # Area = 78.54
print(f'Next year = {year + 1}')          # Next year = 2017

转换标志

在表达式后、冒号前,可用 !s、!r、!a 分别调用 str()、repr()、ascii() 对值进行前置转换:

animals = 'eels'
print(f'My hovercraft is full of {animals}.')      # eels
print(f'My hovercraft is full of {animals!r}.')    # 'eels'

自说明表达式(= 说明符)

在表达式末尾加 =,f-string 会同时输出表达式文本和求值结果,调试时无需手写两遍:

bugs = 'roaches'
count = 13
print(f'Debugging {bugs=} {count=} {area=}')
# Debugging bugs='roaches' count=13 area='living room'

注意:如果表达式包含空格、运算符或属性访问,= 会尽量保留原始文本形式。

格式规范迷你语言

格式规范写在冒号之后,结构为:

[[fill]align][sign][#][0][width][grouping_option][.precision][type]

对齐与填充

  • < 左对齐,> 右对齐,^ 居中,= 仅对数字有效,在符号后填充零。
  • 对齐符号前可指定填充字符,默认是空格。
print(f'{"text":>10}')     # '      text'
print(f'{"text":-<10}')    # 'text------'
print(f'{"text":*^10}')    # '***text***'
print(f'{123:0>8}')        # '00000123'

符号与进制

  • + 强制正数也显示符号;- 仅负数显示(默认);空格表示正数前留空格,便于对齐。
  • # 为二进制、八进制、十六进制添加前缀 0b/0o/0x。
print(f'{42:+d}')          # +42
print(f'{42:d} {42:d}'.format(42, -42))   # '42 -42'  ← 正数前有空格
print(f'{255:#x}')         # 0xff
print(f'{255:b}')          # 11111111
print(f'{255:#010b}')      # 0b11111111  ← 宽度 10,含前缀

数字分组与精度

  • , 按千位分组;_ 同样支持(Python 3.6+)。
  • .precision 对浮点数是小数位数,对字符串是最大字符数。
print(f'{1234567890:,}')           # 1,234,567,890
print(f'{1234567890:_}')          # 1_234_567_890
print(f'{math.pi:.3f}')           # 3.142
print(f'{"hello world":.5}')      # hello

类型码

类型含义
d十进制整数
f / F定点浮点数;F 把 nan/inf 转为大写
e / E科学计数法
g / G自动选择 f 或 e
b / o / x / X二进制、八进制、十六进制
%百分比,自动乘 100
c将整数转为对应 Unicode 字符
print(f'{0.0256:.2%}')      # 2.56%
print(f'{65:c}')            # A
print(f'{1e6:.2e}')         # 1.00e+06

日期格式化

对 datetime 对象,格式规范委托给对象的 __format__ 方法,使用 strftime 风格代码:

from datetime import datetime
dt = datetime(2024, 6, 1, 14, 30, 0)
print(f'{dt:%Y-%m-%d %H:%M:%S}')   # 2024-06-01 14:30:00
print(f'{dt:%A, %B %d}')           # Saturday, June 01

常用日期代码:%Y 四位年份,%m 月份,%d 日期,%H 24小时,%M 分钟,%S 秒,%A 星期全称,%B 月份全称。

性能与选择建议

f-string 在运行时直接求值并编译为高效的字符串构建字节码,速度显著快于 % 和 str.format()。除非需要维护 Python 3.5 及以下代码,否则新代码应无条件使用 f-string。str.format() 仍适用于模板字符串需要与数据分离的场景(如国际化翻译文件)。% 格式化仅建议在修改遗留代码时保持一致性。

总结

字符串格式化的核心在于格式规范迷你语言:对齐、宽度、填充、精度、类型码、分组符等规则在 %(有限支持)、str.format() 和 f-string 中一脉相承。f-string 凭借内联表达式、= 调试语法和最优性能,成为 Python 3.6+ 的绝对首选。掌握 {expression:fill_align_width.precision_type} 这一通用模式,即可覆盖绝大多数格式化需求。

上一页
上下文管理器
下一页
JSON 与 CSV