与 str() 不同的 f 字符串表示

f-string representation different than str()

我一直认为 f-strings 调用了 __str__ 方法。也就是说,f'{x}' 始终与 str(x) 相同。但是,有了这个 class

class Thing(enum.IntEnum):
    A = 0

f'{Thing.A}''0'str(Thing.A)'Thing.A'。如果我使用 enum.Enum 作为基础 class.

,则此示例不起作用

f 字符串调用哪些功能?

来自 "Formatted string literals" in the Python reference: f-strings 调用“format 协议”,与 format built-in 函数相同。这意味着 __format__ 魔术方法被调用而不是 __str__.

class Foo:
    def __repr__(self):
        return "Foo()"

    def __str__(self):
        return "A wild Foo"
    
    def __format__(self, format_spec):
        if not format_spec:
            return "A formatted Foo"
        return f"A formatted Foo, but also {format_spec}!"

>>> foo = Foo()
>>> repr(foo)
'Foo()'
>>> str(foo)
'A wild Foo'
>>> format(foo)
'A formatted Foo'
>>> f"{foo}"
'A formatted Foo'
>>> format(foo, "Bar")
'A formatted Foo, but also Bar!'
>>> f"{foo:Bar}"
'A formatted Foo, but also Bar!'

如果不想调用__format__,可以指定!s(for str),!r(for repr)或表达式后的 !a(对于 ascii):

>>> foo = Foo()
>>> f"{foo}"
'A formatted Foo'
>>> f"{foo!s}"
'A wild Foo'
>>> f"{foo!r}"
'Foo()'

这有时对字符串有用:

>>> key = 'something\n nasty!'
>>> error_message = f"Key not found: {key!r}"
>>> error_message
"Key not found: 'something\n nasty!'"

f-strings 在 Python 中不要使用 __str____repr__。他们使用 __format__。 因此,要获得与 f'{Thing.A}' 相同的结果,您需要调用 format(Thing.A).

__format__(...) 方法允许您添加更多格式化功能(例如,您可以使用浮点数 {:.2f} 将数字四舍五入到两位小数)。

如果没有为 class/object 定义 format(),python 将回退到 __str__。这就是为什么大多数人认为 str() 是 f-strings.

中使用的方法

文档详细介绍了 __format__ 的选项:Link to Documentation