--- doc_type: short full_text: sources/03_Formatting.md --- # 03_Formatting 总结 本文讲解 Python 中用于生成结构化文本输出的字符串格式化技术,重点服务于数据处理场景中的表格输出,例如股票投资组合报表。内容承接前文的容器与数据读取练习,并为后续更复杂的数据展示打基础。相关主题可延伸为 Python字符串格式化、[[concepts/表格化输出]]、股票投资组合报表。 ## 核心主题 在处理数据时,经常需要把原始数据整理成易读的结构化输出,例如对齐的表格: ```text 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}` 形式,将表达式的值插入字符串,并按指定格式显示。 示例: ```python name = 'IBM' shares = 100 price = 91.1 f'{name:>10s} {shares:>10d} {price:>10.2f}' ``` 结果: ```python ' IBM 100 91.10' ``` 这里的格式说明含义是: - `{name:>10s}`:字符串右对齐,占 10 个字符宽度 - `{shares:>10d}`:十进制整数右对齐,占 10 个字符宽度 - `{price:>10.2f}`:浮点数右对齐,占 10 个字符宽度,保留 2 位小数 f-string 通常和 `print()` 搭配使用,但它本质上只是生成字符串,并不依赖打印。 ## 常用格式代码 格式代码位于 `{}` 中冒号 `:` 后面,风格类似 C 语言 `printf()`。 常见类型代码包括: ```text d 十进制整数 b 二进制整数 x 十六进制整数 f 浮点数,形如 [-]m.dddddd e 科学计数法浮点数,形如 [-]m.dddddde+-xx g 浮点数,根据情况选择普通或科学计数法 s 字符串 c 字符,由整数转换而来 ``` 常见修饰符包括: ```text :>10d 整数右对齐,占 10 个字符宽度 :<10d 整数左对齐,占 10 个字符宽度 :^10d 整数居中,占 10 个字符宽度 :0.2f 浮点数保留 2 位小数 ``` 这些规则是 Python字符串格式化 的基础,也直接支撑 [[concepts/表格化输出]]。 ## 字典格式化:format_map() `format_map()` 可将一个字典中的值应用到格式化字符串中。 示例: ```python s = { 'name': 'IBM', 'shares': 100, 'price': 91.1 } '{name:>10s} {shares:10d} {price:10.2f}'.format_map(s) ``` 输出: ```python ' IBM 100 91.10' ``` 它使用与 f-string 相同的格式代码,但值来自传入字典。这种方式适合数据本身已经以字典形式组织的场景,和前文容器相关内容可关联到 Python容器。 ## format() 方法 `format()` 方法可以通过关键字参数或位置参数传入值。 关键字参数示例: ```python '{name:>10s} {shares:10d} {price:10.2f}'.format( name='IBM', shares=100, price=91.1 ) ``` 位置参数示例: ```python '{:>10s} {:10d} {:10.2f}'.format('IBM', 100, 91.1) ``` 两者都会产生类似输出: ```python ' IBM 100 91.10' ``` 不过本文认为 `format()` 相对冗长,日常更推荐 f-string。 ## C 风格 `%` 格式化 Python 也支持 `%` 运算符进行字符串格式化。 示例: ```python 'The value is %d' % 3 '%5d %-5d %10d' % (3, 4, 5) '%0.2f' % (3.1415926,) ``` 这种方式要求右侧是一个单独值或元组,格式代码同样源自 C 的 `printf()`。 特别注意:字节串 `bytes` 只支持这种 `%` 格式化方式。 ```python b'%s has %d messages' % (b'Dave', 37) b'%b has %d messages' % (b'Dave', 37) ``` 这说明 `%` 格式化虽然较旧,但在处理 `bytes` 时仍然重要。 ## 练习 2.8:数字格式化 本练习强调打印数字时如何控制小数位数、字段宽度、对齐方式、填充字符和千位分隔符。 示例: ```python value = 42863.1 print(f'{value:0.4f}') print(f'{value:>16.2f}') print(f'{value:<16.2f}') print(f'{value:*>16,.2f}') ``` 输出效果包括: ```text 42863.1000 42863.10 42863.10 *******42,863.10 ``` 关键点: - `.4f` 表示保留 4 位小数 - `>16.2f` 表示右对齐,占 16 位,保留 2 位小数 - `<16.2f` 表示左对齐 - `*>16,.2f` 表示用 `*` 填充,右对齐,带千位分隔符,保留 2 位小数 练习也展示了 `%` 格式化的等价写法: ```python print('%0.4f' % value) print('%16.2f' % value) ``` 重要结论:格式化结果可以保存为变量,而不一定立即打印。 ```python f = '%0.4f' % value ``` ## 练习 2.9:收集报表数据 本练习要求扩展之前的 `report.py`,根据股票投资组合和价格字典生成报表数据。 目标是实现函数: ```python def make_report(portfolio, prices): ... ``` 输入: - `portfolio`:股票持仓列表 - `prices`:当前价格字典 输出: - 一个由元组组成的列表 - 每个元组表示报表的一行 - 元组字段为:股票名、股数、当前价格、价格变化 示例结果: ```python ('AA', 100, 9.22, -22.980000000000004) ('IBM', 50, 106.28, 15.180000000000007) ('CAT', 150, 35.46, -47.98) ``` 这一步强调先收集结构化数据,再处理输出格式。它把数据计算和数据显示分开,是 数据处理流程 中的重要设计思想。 ## 练习 2.10:打印格式化表格 在获得 `make_report()` 的结果后,本练习要求将元组格式化输出为整齐表格。 使用 `%` 格式化: ```python for r in report: print('%10s %10d %10.2f %10.2f' % r) ``` 或者使用 f-string,并先解包元组: ```python for name, shares, price, change in report: print(f'{name:>10s} {shares:>10d} {price:>10.2f} {change:>10.2f}') ``` 输出示例: ```text AA 100 9.22 -22.98 IBM 50 106.28 15.18 CAT 150 35.46 -47.98 ``` 这里体现了两个关键技能: - 元组解包 - 将不同类型的数据按列宽对齐输出 相关主题包括 元组解包 和 [[concepts/表格化输出]]。 ## 练习 2.11:添加表头和分隔线 本练习要求给报表添加表头: ```python headers = ('Name', 'Shares', 'Price', 'Change') ``` 目标表头字符串: ```python ' Name Shares Price Change' ``` 还要生成分隔线: ```python '---------- ---------- ---------- -----------' ``` 最终输出应为: ```text 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:格式化挑战:货币符号 最后的挑战要求修改价格列,使其包含美元符号 `$`。 目标效果: ```text 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容器:本章练习依赖列表、字典和元组等容器组织数据。 - 元组解包:在格式化报表行时将一行数据拆成多个变量。 ## Related Concepts - [[concepts/字符串处理]] - [[concepts/Python-输入输出]] - [[concepts/元组与解包]] - [[concepts/浮点数精度]] - [[concepts/CSV-数据处理]] - [[concepts/字典与数据建模]] - [[concepts/函数]] - [[concepts/列表与序列]] - [[concepts/Python-容器]] - [[concepts/课程练习工作流]]