Files

9.2 KiB

doc_type, full_text
doc_type full_text
short sources/03_Formatting.md

03_Formatting 总结

本文讲解 Python 中用于生成结构化文本输出的字符串格式化技术,重点服务于数据处理场景中的表格输出,例如股票投资组合报表。内容承接前文的容器与数据读取练习,并为后续更复杂的数据展示打基础。相关主题可延伸为 Python字符串格式化、concepts/表格化输出、股票投资组合报表。

核心主题

在处理数据时,经常需要把原始数据整理成易读的结构化输出,例如对齐的表格:

      Name      Shares        Price
----------  ----------  -----------
        AA         100        32.20
       IBM          50        91.10

本文介绍了多种 Python 字符串格式化方式:

  • f-string,即格式化字符串字面量
  • str.format_map(),从字典中取值格式化
  • str.format(),通过位置参数或关键字参数格式化
  • C 风格 % 格式化

其中,作者明显偏好 Python 3.6+ 的 f-string,因为它简洁、直观,适合常规字符串输出。

f-string 格式化

f-string 使用 {expression:format} 形式,将表达式的值插入字符串,并按指定格式显示。

示例:

name = 'IBM'
shares = 100
price = 91.1

f'{name:>10s} {shares:>10d} {price:>10.2f}'

结果:

'       IBM        100      91.10'

这里的格式说明含义是:

  • {name:>10s}:字符串右对齐,占 10 个字符宽度
  • {shares:>10d}:十进制整数右对齐,占 10 个字符宽度
  • {price:>10.2f}:浮点数右对齐,占 10 个字符宽度,保留 2 位小数

f-string 通常和 print() 搭配使用,但它本质上只是生成字符串,并不依赖打印。

常用格式代码

格式代码位于 {} 中冒号 : 后面,风格类似 C 语言 printf()。

常见类型代码包括:

d       十进制整数
b       二进制整数
x       十六进制整数
f       浮点数,形如 [-]m.dddddd
e       科学计数法浮点数,形如 [-]m.dddddde+-xx
g       浮点数,根据情况选择普通或科学计数法
s       字符串
c       字符,由整数转换而来

常见修饰符包括:

:>10d   整数右对齐,占 10 个字符宽度
:<10d   整数左对齐,占 10 个字符宽度
:^10d   整数居中,占 10 个字符宽度
:0.2f   浮点数保留 2 位小数

这些规则是 Python字符串格式化 的基础,也直接支撑 concepts/表格化输出。

字典格式化:format_map()

format_map() 可将一个字典中的值应用到格式化字符串中。

示例:

s = {
    'name': 'IBM',
    'shares': 100,
    'price': 91.1
}

'{name:>10s} {shares:10d} {price:10.2f}'.format_map(s)

输出:

'       IBM        100      91.10'

它使用与 f-string 相同的格式代码,但值来自传入字典。这种方式适合数据本身已经以字典形式组织的场景,和前文容器相关内容可关联到 Python容器。

format() 方法

format() 方法可以通过关键字参数或位置参数传入值。

关键字参数示例:

'{name:>10s} {shares:10d} {price:10.2f}'.format(
    name='IBM', shares=100, price=91.1
)

位置参数示例:

'{:>10s} {:10d} {:10.2f}'.format('IBM', 100, 91.1)

两者都会产生类似输出:

'       IBM        100      91.10'

不过本文认为 format() 相对冗长,日常更推荐 f-string。

C 风格 % 格式化

Python 也支持 % 运算符进行字符串格式化。

示例:

'The value is %d' % 3
'%5d %-5d %10d' % (3, 4, 5)
'%0.2f' % (3.1415926,)

这种方式要求右侧是一个单独值或元组,格式代码同样源自 C 的 printf()。

特别注意:字节串 bytes 只支持这种 % 格式化方式。

b'%s has %d messages' % (b'Dave', 37)
b'%b has %d messages' % (b'Dave', 37)

这说明 % 格式化虽然较旧,但在处理 bytes 时仍然重要。

练习 2.8:数字格式化

本练习强调打印数字时如何控制小数位数、字段宽度、对齐方式、填充字符和千位分隔符。

示例:

value = 42863.1

print(f'{value:0.4f}')
print(f'{value:>16.2f}')
print(f'{value:<16.2f}')
print(f'{value:*>16,.2f}')

输出效果包括:

42863.1000
        42863.10
42863.10
*******42,863.10

关键点:

  • .4f 表示保留 4 位小数
  • >16.2f 表示右对齐,占 16 位,保留 2 位小数
  • <16.2f 表示左对齐
  • *>16,.2f 表示用 * 填充,右对齐,带千位分隔符,保留 2 位小数

练习也展示了 % 格式化的等价写法:

print('%0.4f' % value)
print('%16.2f' % value)

重要结论:格式化结果可以保存为变量,而不一定立即打印。

f = '%0.4f' % value

练习 2.9:收集报表数据

本练习要求扩展之前的 report.py,根据股票投资组合和价格字典生成报表数据。

目标是实现函数:

def make_report(portfolio, prices):
    ...

输入:

  • portfolio:股票持仓列表
  • prices:当前价格字典

输出:

  • 一个由元组组成的列表
  • 每个元组表示报表的一行
  • 元组字段为:股票名、股数、当前价格、价格变化

示例结果:

('AA', 100, 9.22, -22.980000000000004)
('IBM', 50, 106.28, 15.180000000000007)
('CAT', 150, 35.46, -47.98)

这一步强调先收集结构化数据,再处理输出格式。它把数据计算和数据显示分开,是 数据处理流程 中的重要设计思想。

练习 2.10:打印格式化表格

在获得 make_report() 的结果后,本练习要求将元组格式化输出为整齐表格。

使用 % 格式化:

for r in report:
    print('%10s %10d %10.2f %10.2f' % r)

或者使用 f-string,并先解包元组:

for name, shares, price, change in report:
    print(f'{name:>10s} {shares:>10d} {price:>10.2f} {change:>10.2f}')

输出示例:

        AA        100       9.22     -22.98
       IBM         50     106.28      15.18
       CAT        150      35.46     -47.98

这里体现了两个关键技能:

  • 元组解包
  • 将不同类型的数据按列宽对齐输出

相关主题包括 元组解包 和 concepts/表格化输出。

练习 2.11:添加表头和分隔线

本练习要求给报表添加表头:

headers = ('Name', 'Shares', 'Price', 'Change')

目标表头字符串:

'      Name     Shares      Price      Change'

还要生成分隔线:

'---------- ---------- ---------- -----------'

最终输出应为:

      Name     Shares      Price     Change
---------- ---------- ---------- ----------
        AA        100       9.22     -22.98
       IBM         50     106.28      15.18
       CAT        150      35.46     -47.98
      MSFT        200      20.89     -30.34

这一练习将前面的字段宽度、右对齐和循环输出结合起来,用于构造完整的命令行表格报表。

练习 2.12:格式化挑战:货币符号

最后的挑战要求修改价格列,使其包含美元符号 $。

目标效果:

      Name     Shares      Price     Change
---------- ---------- ---------- ----------
        AA        100      $9.22     -22.98
       IBM         50    $106.28      15.18
       CAT        150     $35.46     -47.98

这要求在数值格式化之外加入字符串拼接或嵌套格式化思路,例如先把价格格式化成带 $ 的字符串,再作为字符串右对齐输出。

该练习强化了一个重要认识:格式化不仅是控制数字精度,也包括构造适合人类阅读的展示形式。

关键知识点

  • f-string 是 Python 3.6+ 中推荐的字符串格式化方式之一。
  • {expression:format} 可同时完成求值与格式控制。
  • 常用控制项包括字段宽度、对齐方向、小数位数、填充字符和千位分隔符。
  • format_map() 适合使用字典数据进行格式化。
  • format() 支持位置参数和关键字参数,但写法较冗长。
  • % 格式化是旧式写法,但仍用于 bytes 格式化。
  • 表格输出通常需要:表头、分隔线、数据行、字段宽度和对齐规则。
  • 数据处理程序应先生成结构化数据,再统一格式化输出。

与其他主题的关系

本文可与以下概念页面建立联系:

  • Python字符串格式化:总结 f-string、format()、format_map() 和 % 格式化。
  • concepts/表格化输出:跨文档整理如何在命令行生成整齐表格。
  • 股票投资组合报表:围绕 portfolio.csv、prices.csv、report.py 的系列练习。
  • 数据处理流程:从读取数据、组织数据、计算结果到格式化输出。
  • Python容器:本章练习依赖列表、字典和元组等容器组织数据。
  • 元组解包:在格式化报表行时将一行数据拆成多个变量。