__format__ 仅在显式格式化(如 f-string、str.format() 或 format() 函数)时触发,不用于 str(obj) 或 print(obj);其 format_spec 参数为冒号后字符串,需手动解析并处理空格、大小写及非法码,且应明确职责——补充而非替代 __str__ 和 __repr__。

为什么 __format__ 没生效?先检查是否用了 f-string 或 str.format()
直接调用 str(obj) 或 print(obj) 不会触发 __format__,它只在显式格式化时才被调用。常见误判是以为打印对象就走这个方法。
- f-string 中写
f"{obj:s}"、f"{obj:.2f}"会调用__format__(self, format_spec) -
"{}".format(obj)同样触发,但"{}".format(obj)等价于__format__(obj, "") -
format(obj, "x")是最干净的测试方式,绕过字符串解析逻辑
__format__ 的 format_spec 参数到底怎么用?
这个字符串就是你写在冒号后面的那部分,比如 f"{obj:08x}" 中的 "08x"。Python 不做预解析,全由你决定怎么解释它——可以支持自定义语法,也可以只兼容内置类型的部分规则。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
- 空字符串
""表示默认格式,常对应str(self)或可读表示 - 若想兼容数字类型行为(如
"f"、".2e"),需手动解析format_spec,推荐用string.Formatter().parse()或正则提取宽度/精度/对齐 - 不识别的格式码建议抛
ValueError,而不是静默忽略,否则调试时难定位问题 - 示例:如果对象有
value属性,__format__(self, spec) = f"{self.value:{spec}}"可透传给内置格式化(仅限数值)
和 __str__、__repr__ 的分工容易混淆
__format__ 不是 __str__ 的替代品,而是补充。三者职责不同:__str__ 是给人看的简明字符串,__repr__ 是给开发者看的无歧义表示,__format__ 是“按需定制显示样式”的入口。
- 不要在
__format__里返回repr(self),除非明确需要调试格式(如f"{obj:!r}"这种场景极少) - 如果对象本质是数值(如带单位的温度类),
__format__应优先支持数字格式码;如果是结构体(如Point(x=1, y=2)),更适合支持"xy"、"json"这类自定义码 - 避免在
__format__中做昂贵计算(如序列化整个嵌套结构),格式化应尽量轻量
真实项目中踩过的坑:格式码大小写、空格、缩进处理
用户输入的 format_spec 可能带空格或大小写混用(如 " 04X "),Python 标准库对数字格式码宽松,但自定义逻辑必须自己清理。
-
format_spec.strip()是底线操作,否则" f"和"f"被视为不同码 - 大小写敏感性要明确:比如
"hex"和"HEX"是否等价,取决于你的设计,但文档里得写清楚 - 不要假设
format_spec一定是字母+符号组合,用户可能传入"[compact]"或'{"indent":2}'这类结构化字符串 - 测试时务必覆盖边界情况:
f"{obj:}"(空)、f"{obj: }"(纯空格)、f"{obj:!@#}"(非法码)
ValueError: unknown format code 'z' for object of type 'Money' 比 unsupported format string passed to Money.__format__ 容易 debug 多了。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










