Python f-strings are impressive!
Did you know you can use f-strings to string format almost anything in Python? You can use them to format floats, multiline strings, decimal places, objects and even use if-else conditionals within them.
In this post, I’ll show you at least 73 examples on how to format strings using Python 3's f-strings. You'll see the many ways you can take advantage of this powerful feature.
By the end of this guide, you'll have mastered:
- how to use f string to format float numbers
- how to format multiline string
- how to define decimal places in a f-string
- how to fix invalid syntax errors such as "syntaxerror: f-string: unmatched '['" or f-string: unmatched '('
- how to use if else statement in a f-string
- basic string interpolation formatting using f-strings
- how to print f-strings
- how to effectively add padding using fstring
Let's go!
Table of Contents
- What Are Python 3's F-Strings - a.k.a Literal String Interpolation?
- How to Format Strings in Python 3 - The Basics
- Limitations
- How to Format an Expression
- How to Use F-Strings to Debug Your Code
- How to Format a Multiline F-String (Dealing with New Lines and Variables)
- How to Fix F-String's Invalid Syntax Error
- How to Fix "formatting a regular string which could be a f-string"
- How to Format Numbers in Different Bases
- How to Print Formatted Objects With F-Strings
- How to Use F-Strings to Format a Float
- How to Format a Number as Percentage
- How to Justify or Add Padding to a F-String
- How to Escape Characters With f-string
-
How to Add a Thousand Separator
15.1. How to Format a Number With Commas as Decimal Separator
15.2. How to Format a Number With Spaces as Decimal Separator
How to Format a Number in Scientific Notation (Exponential Notation)
What Are Python F-Strings - a.k.a Literal String Interpolation?
String formatting has evolved quite a bit in the history of Python. Before Python 2.6, to format a string, one would either use the %
operator, or string.Template
module. Some time later, the str.format
method came along and added to the language a more flexible and robust way of formatting a string.
Old string formatting with %
:
>>> msg = 'hello world'
>>> 'msg: %s' % msg
'msg: hello world'
Using string.format
:
>>> msg = 'hello world'
>>> 'msg: {}'.format(msg)
'msg: hello world'
To simplify formatting even further, in 2015, Eric Smith proposed the
PEP 498 -- Literal String Interpolation
, a new way to format a string for python 3.
PEP 498 presented this new string interpolation to be a simple and easy to use alternative to str.format
. The only thing required is to put a 'f' before a string. And if you're new to the language, that's what f in Python means, it's a new syntax to create formatted strings.
Using f-strings:
>>> msg = 'hello world'
>>> f'msg: {msg}'
'msg: hello world'
And that was it! No need to use str.format
or %
. However, f-strings don’t replace str.format
completely. In this guide I’ll show you an example where they are not suitable.
How to Format Strings in Python 3 - The Basics
As I have shown in the previous section, formatting strings in python using f-strings is quite straightforward. The sole requirement is to provide it a valid expression. f-strings can also start with capital F
and you can combine with raw strings to produce a formatted output. However, you cannot mix them with bytes b""
or "u"
.
>>> book = "The dog guide"
>>> num_pages = 124
>>> f"The book {book} has {num_pages} pages"
'The book The dog guide has 124 pages'
>>> F"The book {book} has {num_pages} pages"
'The book The dog guide has 124 pages'
>>> print(Fr"The book {book} has {num_pages} pages\n")
The book The dog guide has 124 pages\n
>>> print(FR"The book {book} has {num_pages} pages\n")
The book The dog guide has 124 pages\n
>>> print(f"The book {book} has {num_pages} pages\n")
The book The dog guide has 124 pages
And that's pretty much it! In the next section, I'll show you several examples of everything you can do - and cannot do - with f-strings.
Limitations
Even though f-strings are very convenient, they don't replace str.format
completely. f-strings evaluate expressions in the context where they appear. According the the PEP 498
, this means the expression has full access to local and global variables. They're also an expression evaluated at runtime. If the expression used inside the { <expr> }
cannot be evaluated, the interpreter will raise an exception.
>>> f"{name}"
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-f0acc441190f> in <module>
----> 1 f"{name}"
NameError: name 'name' is not defined
This is not a problem for the str.format
method, as you can define the template string and then call .format
to pass on the context.
>>> s = "{name}"
>>> s.format(name="Python")
'Python'
>>> print(s)
{name}
Another limitation is that you cannot use inline comments inside a f-string.
>>> f"My name is {name #name}!"
File "<ipython-input-37-0ae1738dd871>", line 1
f"My name is {name #name}!"
^
SyntaxError: f-string expression part cannot include '#'
How to Format an Expression
If you don't want to define variables, you can use literals inside the brackets. Python will evaluate the expression and display the final result.
>>> f"4 * 4 is {4 * 4}"
'4 * 4 is 16'
Or if you prefer...
>>> n = 4
>>> f"4 * 4 is {n * n}"
'4 * 4 is 16'
How to Use F-Strings to Debug Your Code
One of most frequent usages of f-string is debugging. Before Python 3.8, many people would do hello = 42; f"hello = {hello}"
, but this is very repetitive. As a result, Python 3.8 brought a new feature. You can re-write that expression as f"{hello=}"
and Python will display hello=42
. The following example illustrates this using a function, but the principle is the same.
>>> def magic_number():
...: return 42
...:
>>> f"{magic_number() = }"
'magic_number() = 42'
How to Format a Multiline F-String (Dealing with New Lines and Variables)
You can use the newline character \n
with f-strings to print a string in multiple lines.
>>> multi_line = (f'R: {color["R"]}\nG: {color["G"]}\nB: {color["B"
...: ]}\n')
>>> multi_line
'R: 123\nG: 145\nB: 255\n'
>>> print(multi_line)
R: 123
G: 145
B: 255
As an alternative, you can use triple quotes to represent the multiline string with variables. It not only allows you to add line breaks, it’s also possible to add TAB
.
>>> other = f"""R: {color["R"]}
...: G: {color["G"]}
...: B: {color["B"]}
...: """
>>> print(other)
R: 123
G: 145
B: 255
Example with TAB
s.
>>> other = f'''
...: this is an example
...:
...: ^Iof color {color["R"]}
...:
...: '''
>>> other
'\nthis is an example\n\n\tof color 123\n \n'
>>> print(other)
this is an example
of color 123
>>>
How to Fix F-String's Invalid Syntax Error
If not used correctly, f-strings can raise a SyntaxError
. The most common cause is using double-quotes inside a double quoted f-string. The same is also true for single quotes.
>>> color = {"R": 123, "G": 145, "B": 255}
>>> f"{color["R"]}"
File "<ipython-input-43-1a7f5d512400>", line 1
f"{color["R"]}"
^
SyntaxError: f-string: unmatched '['
# using only single quotes
>>> f'{color['R']}'
File "<ipython-input-44-3499a4e3120c>", line 1
f'{color['R']}'
^
SyntaxError: f-string: unmatched '['
This error not only happens with '['
, but also '('
. The cause is the same, it happens when you close a quote prematurely.
>>> print(f"price: {format(round(12.345), ",")}")
File "<ipython-input-2-1ae6f786bc4d>", line 1
print(f"price: {format(round(12.345), ",")}")
^
SyntaxError: f-string: unmatched '('
To fix that, you need to use single quotes.
>>> print(f"price: {format(round(12.345), ',')}")
price: 12
>>> color = {"R": 123, "G": 145, "B": 255}
>>> f"{color['R']}"
'123'
>>> f'{color["R"]}'
'123'
Another common case is to use f-strings in older versions of Python. f-strings were introduced in Python 3.6. If you use it in an older version, the interpreter will raise a SyntaxError: invalid syntax
.
>>> f"this is an old version"
File "<stdin>", line 1
f"this is an old verion"
^
SyntaxError: invalid syntax
If you see invalid syntax
, make sure to double check the Python version you are running. In my case, I tested in on Python 2.7, and you can find the version by calling sys.version
.
>>> import sys; print(sys.version)
2.7.18 (default, Apr 20 2020, 19:27:10)
[GCC 8.3.0]
How to Fix "formatting a regular string which could be a f-string"
This error happens because pylint detects the old way of formatting string such as using %
or the str.format
method.
C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
To fix that you can either:
- replace the old formatting method with a f-string
- ignore the pylint error using
In this post, I explain how to fix this issue step-by-step.
Replacing with f-strings
The following examples illustrate how to convert old method to f-string.
>>> ip_address = "127.0.0.1"
# pylint complains if we use the methods below
>>> "http://%s:8000/" % ip_address
'http://127.0.0.1:8000/'
>>> "http://{}:8000/".format(ip_address)
'http://127.0.0.1:8000/'
# Replace it with a f-string
>>> f"http://{ip_address}:8000/"
'http://127.0.0.1:8000/'
Disable pylint
Alternatively, you can disable pylint
by specifying the "disable" flag with the error code.
>>> ip_address = "127.0.0.1"
# pylint complains if we use the methods below, so we can disable them
>>> "http://%s:8000/" % ip_address # pylint: disable=C0209
'http://127.0.0.1:8000/'
>>> "http://{}:8000/".format(ip_address) # pylint: disable=C0209
'http://127.0.0.1:8000/'
Another way of disabling that error is to add it to the .pylintrc
file.
# .pylintrc
disable=
...
consider-using-f-string,
...
There's yet another way of disabling it, which is by placing a comment at the top of the file, like so:
# pylint: disable=consider-using-f-string
def your_function(fun):
"""Your code below"""
...
How to Format Numbers in Different Bases
f-strings also allow you to display an integer in different bases. For example, you can display an int
as binary without converting it by using the b
option.
>>> f'{7:b}'
'111'
In summary, you can use f-strings to format:
-
int
to binary -
int
to hex -
int
to octal -
int
to HEX (where all chars are capitalized)
The following example uses the padding feature and the base formatting to create a table that displays an int
in other bases.
>>> bases = {
"b": "bin",
"o": "oct",
"x": "hex",
"X": "HEX",
"d": "decimal"
}
>>> for n in range(1, 21):
...: for base, desc in bases.items():
...: print(f"{n:5{base}}", end=' ')
...: print()
1 1 1 1 1
10 2 2 2 2
11 3 3 3 3
100 4 4 4 4
101 5 5 5 5
110 6 6 6 6
111 7 7 7 7
1000 10 8 8 8
1001 11 9 9 9
1010 12 a A 10
1011 13 b B 11
1100 14 c C 12
1101 15 d D 13
1110 16 e E 14
1111 17 f F 15
10000 20 10 10 16
10001 21 11 11 17
10010 22 12 12 18
10011 23 13 13 19
10100 24 14 14 20
How to Print Formatted Objects With F-Strings
You can print custom objects using f-strings. By default, when you pass an object instance to a f-string, it will display what the __str__
method returns. However, you can also use the explicit conversion flag to display the __repr__
.
!r - converts the value to a string using repr().
!s - converts the value to a string using str().
>>> class Color:
def __init__(self, r: float = 255, g: float = 255, b: float = 255):
self.r = r
self.g = g
self.b = b
def __str__(self) -> str:
return "A RGB color"
def __repr__(self) -> str:
return f"Color(r={self.r}, g={self.g}, b={self.b})"
>>> c = Color(r=123, g=32, b=255)
# When no option is passed, the __str__ result is printed
>>> f"{c}"
'A RGB color'
# When `obj!r` is used, the __repr__ output is printed
>>> f"{c!r}"
'Color(r=123, g=32, b=255)'
# Same as the default
>>> f"{c!s}"
'A RGB color'
Python also allows us to control the formatting on a per-type basis through the __format__
method. The following example shows how you can do all of that.
>>> class Color:
def __init__(self, r: float = 255, g: float = 255, b: float = 255):
self.r = r
self.g = g
self.b = b
def __str__(self) -> str:
return "A RGB color"
def __repr__(self) -> str:
return f"Color(r={self.r}, g={self.g}, b={self.b})"
def __format__(self, format_spec: str) -> str:
if not format_spec or format_spec == "s":
return str(self)
if format_spec == "r":
return repr(self)
if format_spec == "v":
return f"Color(r={self.r}, g={self.g}, b={self.b}) - A nice RGB thing."
if format_spec == "vv":
return (
f"Color(r={self.r}, g={self.g}, b={self.b}) "
f"- A more verbose nice RGB thing."
)
if format_spec == "vvv":
return (
f"Color(r={self.r}, g={self.g}, b={self.b}) "
f"- A SUPER verbose nice RGB thing."
)
raise ValueError(
f"Unknown format code '{format_spec}' " "for object of type 'Color'"
)
>>> c = Color(r=123, g=32, b=255)
>>> f'{c:v}'
'Color(r=123, g=32, b=255) - A nice RGB thing.'
>>> f'{c:vv}'
'Color(r=123, g=32, b=255) - A more verbose nice RGB thing.'
>>> f'{c:vvv}'
'Color(r=123, g=32, b=255) - A SUPER verbose nice RGB thing.'
>>> f'{c}'
'A RGB color'
>>> f'{c:s}'
'A RGB color'
>>> f'{c:r}'
'Color(r=123, g=32, b=255)'
>>> f'{c:j}'
--------------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-20-1c0ee8dd74be> in <module>
---------> 1 f'{c:j}'
<ipython-input-15-985c4992e957> in __format__(self, format_spec)
29 f"- A SUPER verbose nice RGB thing."
30 )
--------> 31 raise ValueError(
32 f"Unknown format code '{format_spec}' " "for object of type 'Color'"
33 )
ValueError: Unknown format code 'j' for object of type 'Color'
Lastly, there's also the a
option that escapes non-ASCII chars. For more info: https://docs.python.org/3/library/functions.html#ascii
>>> utf_str = "Áeiöu"
>>> f"{utf_str!a}"
"'\\xc1ei\\xf6u'"
How to Use F-Strings to Format a Float
f-strings allow format float numbers similar to str.format
method. To do that, you can add a :
(colon) followed by a .
(dot) and the number of decimal places with a f
suffix.
For instance, you can round a float to 2 decimal places and print the variable just like this:
>>> num = 4.123956
>>> f"num rounded to 2 decimal places = {num:.2f}"
'num rounded to 2 decimal places = 4.12'
If you don't specify anything, the float variable will use the full precision.
>>> print(f'{num}')
4.123956
How to Format a Number as Percentage
Python f-strings have a very convenient way of formatting percentage. The rules are similar to float formatting, except that you append a %
instead of f
. It multiplies the number by 100 displaying it in a fixed format, followed by a percent sign. You can also specify the precision.
>>> total = 87
>>> true_pos = 34
>>> perc = true_pos / total
>>> perc
0.39080459770114945
>>> f"Percentage of true positive: {perc:%}"
'Percentage of true positive: 39.080460%'
>>> f"Percentage of true positive: {perc:.2%}"
'Percentage of true positive: 39.08%'
How to Justify or Add Padding to a F-String
You can justify a string quite easily using <
or >
characters.
>>> greetings = "hello"
>>> f"She says {greetings:>10}"
'She says hello'
# Pad 10 char to the right
>>> f"{greetings:>10}"
' hello'
>>> f"{greetings:<10}"
'hello '
# You can omit the < for left padding
>>> f"{greetings:10}"
'hello '
>>> a = "1"
>>> b = "21"
>>> c = "321"
>>> d = "4321"
>>> print("\n".join((f"{a:>10}", f"{b:>10}", f"{c:>10}", f"{d:>10}")))
1
21
321
4321
How to Escape Characters With f-string
In case you want to display the variable name surrounded by the curly brackets instead of rendering its value, you can escape it using double {{<expr>}}
.
>>> hello = "world"
>>> f"{{hello}} = {hello}"
'{hello} = world'
Now, if you want to escape a double quote, you can use the backslash \"
.
>>> f"{hello} = \"hello\""
'world = "hello"'
How to Center a String
Centering a string can be achieved by using var:^N
where var
is a variable you want to display and N
is the string length. If N
is shorter than the var
, then Python display the whole string.
>>> hello = "world"
>>> f"{hello:^11}"
' world '
>>> f"{hello:*^11}"
'***world***'
# Extra padding is added to the right
>>> f"{hello:*^10}"
'**world***'
# N shorter than len(hello)
>>> f"{hello:^2}"
'world'
How To Add a Thousand Separator
f-strings also allow us to customize numbers. One common operation is to add an underscore to separate every thousand place.
>>> big_num = 1234567890
>>> f"{big_num:_}"
'1_234_567_890'
How to Format a Number With Commas as Decimal Separator
In fact, you can use any char as separator. It’s also possible to use a comma as separator.
>>> big_num = 1234567890
>>> f"{big_num:,}"
'1,234,567,890'
You can also format a float with commas and set the precision in one go.
>>> num = 2343552.6516251625
>>> f"{num:,.3f}"
'2,343,552.652'
How to Format a Number With Spaces as Decimal Separator
What about using spaces instead?
Well, this one is a bit “hacky” but it works. You can use the ,
as separator, then replace it with space.
>>> big_num = 1234567890
>>> f"{big_num:,}".replace(',', ' ')
'1 234 567 890'
Another option is to set the locale of your environment to one that uses spaces as a thousand separator such as pl_PL
. For more info, see this thread on stack overflow.
How to Format a Number in Scientific Notation (Exponential Notation)
Formatting a number in scientific notation is possible with the e
or E
option.
>>> num = 2343552.6516251625
>>> f"{num:e}"
'2.343553e+06'
>>> f"{num:E}"
'2.343553E+06'
>>> f"{num:.2e}"
'2.34e+06'
>>> f"{num:.4E}"
'2.3436E+06'
Using if-else
Conditional in a F-String
f-strings also evaluates more complex expressions such as inline if/else
.
>>> a = "this is a"
>>> b = "this is b"
>>> f"{a if 10 > 5 else b}"
'this is a'
>>> f"{a if 10 < 5 else b}"
'this is b'
How to Use F-String With a Dictionary
You can use dictionaries in a f-string. The only requirement is to use a different quotation mark than the one enclosing the expression.
>>> color = {"R": 123, "G": 145, "B": 255}
>>> f"{color['R']}"
'123'
>>> f'{color["R"]}'
''123'
>>> f"RGB = ({color['R']}, {color['G']}, {color['B']})"
'RGB = (123, 145, 255)'
How to Concatenate F-Strings
Concatenating f-strings is like concatenating regular strings, you can do that implicitly, or explicitly by applying the +
operator or using str.join
method.
# Implicit string concatenation
>>> f"{123}" " = " f"{100}" " + " f"{20}" " + " f"{3}"
'123 = 100 + 20 + 3'
# Explicity concatenation using '+' operator
>>> f"{12}" + " != " + f"{13}"
'12 != 13'
# string concatenation using `str.join`
>>> " ".join((f"{13}", f"{45}"))
'13 45'
>>> "#".join((f"{13}", f"{45}"))
'13#45'
How to Format a Date With F-String
f-strings also support the formatting of datetime
objects. The process is very similar to how str.format
formats dates. For more info about the supported formats, check this table in the official docs.
>>> import datetime
>>> now = datetime.datetime.now()
>>> ten_days_ago = now - datetime.timedelta(days=10)
>>> f'{ten_days_ago:%Y-%m-%d %H:%M:%S}'
'2020-10-13 20:24:17'
>>> f'{now:%Y-%m-%d %H:%M:%S}'
'2020-10-23 20:24:17'
How to Add Leading Zeros
You can add leading zeros by adding using the format {expr:0len}
where len
is the length of the returned string. You can include a sign option. In this instance, +
means the sign should be used for positive and negative numbers. The -
is used only for negative numbers, which is the default behavior. For more info, check the string format specification page .
>>> num = 42
>>> f"{num:05}"
'00042'
>>> f'{num:+010}'
'+000000042'
>>> f'{num:-010}'
'0000000042'
>>> f"{num:010}"
'0000000042'
>>> num = -42
>>> f'{num:+010}'
'-000000042'
>>> f'{num:010}'
'-000000042'
>>> f'{num:-010}'
'-000000042'
Conclusion
That’s it for today, folks! I hope you’ve learned something different and useful. Knowing how to make the most out of f-string can make our lives so much easier. In this post, I showed the most common tricks I use in a day-to-day basis.
Other posts you may like:
- How to Check if an Exception Is Raised (or Not) With pytest
- Everything You Need to Know About Python's Namedtuples
- The Best Way to Compare Two Dictionaries in Python
- 11 Useful Resources To Learn Python's Internals From Scratch
- 7 pytest Features and Plugins That Will Save You Tons of Time
See you next time!
Top comments (0)