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

Why does adding formatting information to a f-string with tuple values raise a TypeError?

我试图了解 Python 中 f 弦的以下行为:

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

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

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

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

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

f"{(1,2,3)}"

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

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

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

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

如您所见,有些神奇的事情正在发生。但是,不是每个项目在格式化之前只是被转换为字符串。

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

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

所以根据format_spec.

生成和return一个字符串将取决于你自己MyType.__format__

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

你可以做的是使用 ! 标记将元组转换为字符串——这等同于使用 str() 但不那么冗长:

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

输出' (1, 2, 3)'

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