I had always thought that f-strings invoked the __str__
method. That is, f'{x}'
was always the same as str(x)
. However, with this class
class Thing(enum.IntEnum):
A = 0
f'{Thing.A}'
is '0'
while str(Thing.A)
is 'Thing.A'
. This example doesn't work if I use enum.Enum
as the base class.
What functionality do f-strings invoke?
From "Formatted string literals" in the Python reference:
f-strings invoke the "format()
protocol", meaning that the __format__
magic method is called instead of __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!'
If you don't want __format__
to be called, you can specify !s
(for str
), !r
(for repr
) or !a
(for ascii
) after the expression:
>>> foo = Foo()
>>> f"{foo}"
'A formatted Foo'
>>> f"{foo!s}"
'A wild Foo'
>>> f"{foo!r}"
'Foo()'
This is occasionally useful with strings:
>>> key = 'something\n nasty!'
>>> error_message = f"Key not found: {key!r}"
>>> error_message
"Key not found: 'something\\n nasty!'"