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.

Answer from Dimitris Fasarakis Hilliard on Stack Overflow
🌐
Python
peps.python.org › pep-0498
PEP 498 – Literal String Interpolation | peps.python.org
The allowed conversions are '!s', '!r', or '!a'. These are treated the same as in str.format(): '!s' calls str() on the expression, '!r' calls repr() on the expression, and '!a' calls ascii() on the expression. These conversions are applied before the call to format(). The only reason to use '!s' is if you want to specify a format specifier that applies to str, not to the type of the expression. F-strings use the same format specifier mini-language as str.format.
🌐
Real Python
realpython.com › python-f-strings
Python's F-String for String Interpolation and Formatting – Real Python
November 30, 2024 - In the first f-string, you use the !s tag to interpolate the string representation that .__str__() returns. In the second f-string, you use the !r flag to interpolate the developer-friendly string representation of your current object. These two flags are pretty relevant for you as a Python developer.
🌐
Python Morsels
pythonmorsels.com › string-formatting
Python f-string tips & cheat sheets - Python Morsels
April 12, 2022 - With self-documenting expressions, the resulting replacement string includes the original replacement field expression as well as the result with an = sign separating them. Note that the repr representation is used by default.
Top answer
1 of 2
107

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!'"
2 of 2
43

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

🌐
DigitalOcean
digitalocean.com › community › tutorials › how-to-use-f-strings-to-create-strings-in-python-3
How To Use f-strings to Create Strings in Python 3 | DigitalOcean
September 10, 2020 - In the second example, we add the !r modifier to the end of the expression embedded in the f-string. !r instructs Python to call repr on now to generate a string representation. In general, repr prints debugging information more suitable for the interactive Python interpreter.
🌐
Codecademy Forums
discuss.codecademy.com › get help › python
F-strings in Class __repr__ Method - Python - Codecademy Forums
November 14, 2018 - https://www.codecademy.com/paths/computer-science/tracks/cspath-cumulative-art-marketplace/modules/cspath-veneer/projects/veneer I’m trying to set a class __repr__ method using f-strings. I know this isn’t necessary, and know how to do this using %-formatting or str.format() - I’ve not used f-strings before and wanted to try them out. class Art: def __init__(self, artist, title, medium, year): self.artist = artist self.title = title self.medium = medium self.year = year ...
🌐
Martin Heinz
martinheinz.dev › blog › 70
Python f-strings Are More Powerful Than You Might Think | Martin Heinz | Personal Website & Blog
April 4, 2022 - We could also just call repr(some_var) inside the f-string, but using the conversion flag is a nice native and concise solution. Powerful features and syntax sugar oftentimes comes with performance penalty, that's however not the case when it comes to f-strings: # python -m timeit -s 'x, y = "Hello", "World"' 'f"{x} {y}"' from string import Template x, y = "Hello", "World" print(f"{x} {y}") # 39.6 nsec per loop - Fast!
Find elsewhere
🌐
Towards Data Science
towardsdatascience.com › home › latest › python f-strings are more powerful than you might think
Python f-strings Are More Powerful Than You Might Think | Towards Data Science
March 5, 2025 - We could also just call repr(some_var) inside the f-string, but using the conversion flag is a nice native and concise solution. Powerful features and syntax sugar oftentimes comes with performance penalty, that’s however not the case when it comes to f-strings: The above samples were tested with timeit module like so: python -m timeit -s 'x, y = "Hello", "World"' 'f"{x} {y}"' and as you can see f-strings are actually the fastest of all formatting options Python provides.
🌐
Reddit
reddit.com › r/python › in case you didn't know: python 3.8 f-strings support = for self-documenting expressions and debugging
r/Python on Reddit: In case you didn't know: Python 3.8 f-strings support = for self-documenting expressions and debugging
August 26, 2020 -

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
🌐
Python documentation
docs.python.org › 3 › tutorial › inputoutput.html
7. Input and Output — Python 3.14.3 documentation
When you don’t need fancy output but just want a quick display of some variables for debugging purposes, you can convert any value to a string with the repr() or str() functions.
🌐
DigitalOcean
digitalocean.com › community › tutorials › python-str-repr-functions
How To Use the __str__() and __repr__() Methods in Python | DigitalOcean
October 8, 2025 - Quick Answer: __str__() and __repr__() are Python’s special methods that control how objects are displayed as strings. __str__() creates user-friendly output for end users, while __repr__() creates detailed, developer-focused output that ideally can recreate the object.
🌐
Tirkarthi
tirkarthi.github.io › programming › 2019 › 05 › 08 › f-string-debugging.html
f-string debugging in Python 3.8
May 8, 2019 - This caused users to write f"name = {name}" and can get unwieldy when variable names are long like filtered_data_from_third_party would be written as f"filtered_data_from_third_party = {filtered_data_from_third_party}". In those cases we resort to shorter names we understand easily at the context like f"filtered data {filtered_data_from_third_pary}". f-strings also support format specifiers so you can write f"{name!r}" which is same as f"{repr(name)}". Given the above boilerplate an idea was posted in python-ideas around a format specifier where you can use it and the f-string would expand like a macro into <variable_name> = <value_of_variable>. Initially !d was chosen so f"{name!d}" would expand to f"name={repr(name)}".
🌐
ZetCode
zetcode.com › python › fstring
Python f-string - formatting strings in Python with f-string
May 11, 2025 - Python f-string tutorial shows how to format strings in Python with f-string. Python f-strings provide a faster, more readable, concise, and less error prone way of formatting strings in Python.
🌐
Jerry Ng
jerrynsh.com › 3-useful-python-f-string-tricks-you-probably-dont-know
3 Useful Python F-string Tricks You Probably Don’t Know
July 3, 2024 - When you use an exclamation mark syntax, !, followed by your variable in your f-string, it will perform extra conversion on that variable. For instance, you can easily print out the ASCII representation of your string with f’{your_variable!a}’, just like this:
🌐
Medium
medium.com › bitgrit-data-science-publication › python-f-strings-tricks-you-should-know-7ce094a25d43
Python F-strings Tricks You Should Know | by Benedict Neo | bitgrit Data Science Publication | Medium
October 12, 2022 - With a str the method defined, you’d need to write !r to tell Python to print out the repr method instead. If you want your variables to be printed at a specific position, alignments are the way to go! Notice in the first line number:n . Here n stands for the width of space to print the variable number starting from the string “is” (inclusive of the variable itself)
🌐
30 Seconds of Code
30secondsofcode.org › home › python › 6 python f-strings tips and tricks
6 Python f-strings tips and tricks - 30 seconds of code
July 20, 2021 - Apart from plain string interpolation, you might want to get the printable representation of a value. This is already easy to accomplish using the repr() function.
🌐
Stack Abuse
stackabuse.com › string-formatting-with-python-3s-f-strings
String Formatting with Python 3's f-Strings
September 19, 2021 - If we wanted to use an f-String with the __repr_() method of an object, you can put an !r in front of your object being substituted. Edit the fstring_classes.py file and change the last line: ... F-Strings, like any other Python string, support the use of backslashes to escape characters.