Python f‑strings are a modern, highly expressive way to format text, introduced in
Python 3.6. They allow you to embed expressions directly inside string literals
using a clear and compact syntax. Compared to older formatting techniques such as %
formatting or str.format(), f‑strings are faster, more readable, and
less error‑prone. Because the expressions are evaluated at runtime, they also make
it easy to include variables, function calls, and even inline calculations directly
within the string, which leads to cleaner and more maintainable code.
The f-strings have the f prefix and use {} brackets to evaluate values.
name = 'John Doe'
occupation = 'gardener'
age = 34
msg = f'''name: {name}
age: {age}
occupation: {occupation}'''
print(msg)Format specifiers for types, padding, or aligning are specified after the colon character;
for instance: f'{price:.3}', where price is a variable name.
The following example summarizes string formatting options in Python.
name = 'Peter'
age = 23
print('%s is %d years old' % (name, age))
print('{} is {} years old'.format(name, age))
print(f'{name} is {age} years old')The example formats a string using two variables.
print('%s is %d years old' % (name, age))This is the oldest option. It uses the % operator and classic string format specifies such as %s and %d.
print('{} is {} years old'.format(name, age))Since Python 3.0, the format function was introduced to provide advance formatting options.
print(f'{name} is {age} years old')Python f-strings are available since Python 3.6. The string has the f prefix and uses {} to evaluate variables.
$ python formatting_string.py
Peter is 23 years old
Peter is 23 years old
Peter is 23 years old
We can put expressions between the {} brackets.
bags = 3
apples_in_bag = 12
print(f'There are total of {bags * apples_in_bag} apples')The example evaluates an expression inside f-string.
$ python expressions.py
There are total of 36 apples
We can work with dictionaries in f-strings.
user = {'name': 'John Doe', 'occupation': 'gardener'}
print(f"{user['name']} is a {user['occupation']}")The example evaluates a dictionary in an f-string.
$ python dicts.py
John Doe is a gardener
Python 3.8 introduced the self-documenting expression with the = character.
import math
x = 0.8
print(f'{math.cos(x) = }')
print(f'{math.sin(x) = }')The example outputs the Sine and Cosine functions in the debug mode.
$ python debug.py
math.cos(x) = 0.6967067093471654
math.sin(x) = 0.7173560908995228
We can work with multiline strings.
name = 'John Doe'
occupation = 'gardener'
age = 34
msg = f'''name: {name}
age: {age}
occupation: {occupation}'''
print(msg)The example presents a multiline f-string.
$ python main.py
name: John Doe
age: 34
occupation: gardener
We can also call functions in f-strings.
def mymax(x, y):
return x if x > y else y
a = 3
b = 4
print(f'Max of {a} and {b} is {mymax(a, b)}')The example calls a custom function in the f-string.
$ python main.py
Max of 3 and 4 is 4
Python f-string accepts objects as well; the objects must have either __str__ or __repr__
magic functions defined.
class User:
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation
def __repr__(self):
return f"{self.name} is a {self.occupation}"
u = User('John Doe', 'gardener')
print(f'{u}')The example evaluates an object in the f-string.
$ python main.py
John Doe is a gardener
The __format__ method gives us more control over how an object is formatted within
an f-string. It allows us to define custom formatting behavior based on the format
specifier provided within the f-string.
from dataclasses import dataclass
@dataclass
class User:
name: str
occupation: str
def __format__(self, spec):
return f'User(name={self.name}{spec} occupation={self.occupation})'
u1 = User('John Doe', 'gardener')
u2 = User('Roger Roe', 'driver')
u3 = User('Lucia Smith', 'teacher')
print(f'{u1:-}')
print(f'{u2:;}')
print(f'{u3:#}')We define a data object with a custom __format__ method.
The following example shows how to escape certain characters in f-strings.
print(f'Python uses {{}} to evaludate variables in f-strings')
print(f'This was a \'great\' film')To escape a curly bracket, we double the character. A single quote is escaped with a backslash character.
$ python escaping.py
Python uses {} to evaludate variables in f-strings
This was a 'great' film
The following example formats datetime.
import datetime
now = datetime.datetime.now()
print(f'{now:%Y-%m-%d %H:%M}')
print(f'{now:%A}')
print(f'{now:%a}')
print(f'{now:%B}')
print(f'{now:%j}')
print(f'{now:%w}')The example displays a formatted current datetime. The datetime format specifiers follow the : character.
$ python format_datetime.py
2023-03-24 15:12
Friday
Fri
March
083
5
It is possible to nest expressions within expressions.
from datetime import datetime
today = datetime.now().date()
spec1 = '%d.%m.%y'
spec2 = '%y/%m/%d'
print(f'{today:{spec1}}')
print(f'{today:{spec2}}')In the example, we use different format specifications. They are provided as
spec variables and are evaluated as nested expressions.
Floating point values have the f suffix. We can also specify the precision: the number of decimal places.
The precision is a value that goes right after the dot character.
val = 12.3
print(f'{val:.2f}')
print(f'{val:.5f}')The example prints a formatted floating point value.
$ python format_floats.py
12.30
12.30000
The output shows the number having two and five decimal places.
We display a decimal value as percentage using the % format specifier.
val = 1/7.0
print(f'{val}')
print(f'{val:.2%}')In the program, we display the 1/7 value as a percentage with two decimal places.
$ python percentage.py
0.14285714285714285
14.29%
The width specifier sets the width of the value. The value may be filled with spaces or other characters
if the value is shorter than the specified width.
for x in range(1, 11):
print(f'{x:02} {x*x:3} {x*x*x:4}')The example prints three columns. Each of the columns has a predefined width. The first column uses
0 to fill shorter values.
$ python format_width.py
01 1 1
02 4 8
03 9 27
04 16 64
05 25 125
06 36 216
07 49 343
08 64 512
09 81 729
10 100 1000
By default, the strings are justified to the left. We can use the > character to justify the strings
to the right. The > character follows the colon character. The < justifies to the left; this can
be omitted. The ^ centers the string.
words = ['sky', 'fork', 'small', 'cup', 'car', 'war']
for word in words:
print(f'|{word:>20}|')
for word in words:
print(f'|{word:^20}|')
for word in words:
print(f'|{word:<20}|')We have a list of words. The words are aligned to the right, center, and left.
Each of the outputs has twenty characters.
$ python main.py
| sky|
| fork|
| small|
| cup|
| car|
| war|
| sky |
| fork |
| small |
| cup |
| car |
| war |
|sky |
|fork |
|small |
|cup |
|car |
|war |
Numbers can have various numeric notations, such as decadic or hexadecimal.
val = 300
# hexadecimal lower
print(f'{val:x}')
# hexadecimal upper
print(f'{val:X}')
# octal
print(f'{val:o}')
# binary
print(f'{val:b}')
# scientific
print(f'{val:e}')The example prints a value in various notations.
$ python format_notations.py
12c
12C
454
100101100
3.000000e+02
We can format numbers with underscore and command thousands separators.
val = 1_200_400_001
print(val)
print(f'{val:_}')
print(f'{val:,}')A big integer is printed in formats where thousand groups are separated with
_ and ,.
$ python main.py
1200400001
1_200_400_001
1,200,400,001