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

Python中__format__方法自定义格式说明符报错问题排查

问题根源:混用了两种Python格式化语法

你遇到的问题核心是把旧式的%格式化语法和新式的str.format()格式规范搞混了,这两种是完全独立的系统,不能直接混用。

先理清两个关键概念:

  • %s、%r是旧式字符串格式化的占位符(比如"Dealer has %r of %s" % (rank, suit)这种写法),和str.format()的{0:xxx}语法完全不兼容。
  • 当你调用"{0:FORMAT}".format(obj)时,obj.__format__()方法收到的参数是冒号后面的FORMAT字符串,而不是整个带%的模板。你原来的代码里试图在__format__里替换%r、%s,但这些占位符根本不属于str.format()的格式规范体系,自然会出问题。

正确的自定义格式实现方式

如果你想给NumberCard类自定义格式说明符,可以自己定义一套格式规则,比如用rs表示"rank of suit",r只显示点数,s只显示花色。示例代码如下:

class NumberCard:
    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit

    def __format__(self, format_spec):
        # 根据格式说明符返回对应字符串
        if format_spec == "rs":
            return f"{self.rank} of {self.suit}"
        elif format_spec == "r":
            return str(self.rank)
        elif format_spec == "s":
            return str(self.suit)
        # 默认情况返回对象的字符串表示
        return str(self)

# 调用方式
print("Dealer has {0:rs}".format(NumberCard(1, "Club")))
# 输出:Dealer has 1 of Club

如果你非要用类似%的写法?

其实没必要,但如果想快速实现类似效果,可以直接在format调用里拆分参数,不用依赖__format__:

card = NumberCard(1, "Club")
print("Dealer has {0} of {1}".format(card.rank, card.suit))

或者在类里实现__str__或__repr__,直接用"{0}".format(card)输出你想要的默认格式。

再回头看你的报错

你的回溯信息里显示format_spec.replace("%r", self.rank).replace("%s...,说明你把%r of %s当成了传给__format__的格式规范,但这完全是错误的用法——str.format()不会解析格式规范里的%占位符,只会原封不动传给__format__,而你的替换操作可能因为代码截断(比如没写完%s的替换)或者类型不匹配(比如self.rank不是字符串)导致报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:27:22