It just calls the repr of the value supplied.
It's usage is generally not really needed with f-strings since with them you can just do repr(self.radius) which is arguably more clear in its intent.
!r (repr), !s (str) and !a (ascii) were kept around just to ease compatibility with the str.format alternative, you don't need to use them with f-strings.
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!'"
f-strings in Python don't use __str__ or __repr__. They use __format__.
So to get the same result as f'{Thing.A}', you'd need to call format(Thing.A).
The __format__(...) method allows you to add more formatting features (for example with floats you can do {:.2f} to round the number to two decimals).
If format() hasn't been defined for a class/object, python will fall back to __str__. That's why most people think str() is the method used in f-strings.
The docs cover the options you have with __format__ in detail: Link to Documentation
Python 3.8 added an = specifier to f-strings. An f-string such as f'{expr=}' will expand to the text of the expression, an equal sign, then the representation of the evaluated expression.
Examples:
input:
from datetime import date
user = 'eric_idle'
member_since = date(1975, 7, 31)
f'{user=} {member_since=}'output:
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
input:
delta = date.today() - member_since
f'{user=!s} {delta.days=:,d}'output (no quotes; commas):
'user=eric_idle delta.days=16,075'
input:
from math import cos,radians
theta=30
print(f'{theta=} {cos(radians(theta))=:.3f}')output:
theta=30 cos(radians(theta))=0.866