You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Python的f-string与str()转换对子类的执行结果不一致?

问题描述

我们在Decimal的子类中重写__str__方法后,用两种方式调用出现结果差异:

from decimal import Decimal
class D(Decimal):
    def __str__(self):
        return super().normalize().__str__()
num = D('1.0')
print(f"{num}")
print(f"{str(num)}")

输出结果:

1.0
1

预期两者都输出1,但第一个print似乎调用了Decimal.__str__而非D.__str__,请问该现象的原因及解决方法?

原因分析

这是因为f-string在格式化对象时,对于部分由C扩展实现的内置类型(比如Decimal),会绕过子类的__str__方法,直接调用父类的原生实现。

Python的f-string底层会优先尝试调用对象的__format__方法,如果没有自定义实现,对于Decimal这类C扩展类型,会直接走内部的快速格式化逻辑,不会触发子类重写的__str__;而str(num)则是按照正常的方法解析顺序,先查找子类的__str__,找不到才会去父类找,所以能正确执行我们重写的逻辑。

解决方法

重写子类的__format__方法,让f-string格式化时也使用我们自定义的逻辑:

from decimal import Decimal
class D(Decimal):
    def __str__(self):
        return super().normalize().__str__()
    
    def __format__(self, format_spec):
        # 复用__str__的逻辑,也可根据format_spec做定制化处理
        return self.__str__()

num = D('1.0')
print(f"{num}")
print(f"{str(num)}")

此时输出会统一为:

1
1

内容的提问来源于stack exchange,提问作者goweon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:19:57