为什么将格式信息添加到具有元组值的 f 字符串会引发 TypeError?

问题描述

我试图了解 Python 中 f 字符串的以下行为:

通过 str() 显式转换元组值的以下行工作正常。

f"{str((1,2,3)):>10}"

但是,如果我删除显式转换,该行会引发 TypeError: unsupported format string passed to tuple.__format__:

f"{(1,3):>20}"

没有给定任何格式时没有问题:

f"{(1,3)}"

我原以为 f-string自动元组转换为字符串,然后强制执行格式要求。情况似乎并非如此。有人可以解释一下吗?除了通过 str() 进行显式转换之外,还有其他解决方法吗?

解决方法

您可以通过使用文字 !s 在字符串的格式部分明确指定转换为字符串来实现,如下所示:

f"{(1,2,3)!s:>10}'

这是必需的,因为宽度规范 :>10 仅适用于字符串。

,

正如您所经历的,有一些魔法正在发生。但是,并非在格式化之前将每个项目都转换为字符串。

TypeError 解释了 Python 试图做什么:它试图调用元组的 __format__ 方法。但它失败了,因为 tuple.__format__ 不需要 > 参数。如果您要微调自己班级的格式,您可以这样做:

class MyType:
    def __init__(self,value):
        self.value = value

    def __format__(self,format_spec):
        return f"this is the value {self.value} formatted against {format_spec}"


if __name__ == '__main__':
    d = MyType(6)

    print(f"{d:>10}")

输出:

this is the value 6 formatted against >10

因此,根据 MyType.__format__ 生成和返回字符串取决于您自己的 format_spec

具有处理 __format__ 之类的 format_spec 方法的 >10 方法的一种原生 Python 类型是字符串类。这就是 f"{str((1,3)):>10}" 起作用的原因。

您可以做的是使用 ! 标记将元组转换为字符串 - 这相当于使用 str() 但不那么冗长:

f"{(1,3)!s:>10}"

输出' (1,3)'

根据需要在左侧添加一个空格。