["python","enums","f-string"]
f-string representation different than str()

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!'"