⇦ Back

f-Strings are a way of formatting your strings. It’s not the only way to do this in Python, but it’s the most powerful.

1 Creating an f-String

An f-string is created by appending the letter “f” to the front of a string and then adding the name of an already-defined variable between curly bracket. The value of that variable will then get incorporated into the string itself.

answer = 10
print(f'The answer is {answer}')
## The answer is 10

Multiple arguments can be incorporated into an f-string, and these can be either numbers or strings:

first = 47
second = 'hi'
print(f'First argument: {first}, second one: {second}')
## First argument: 47, second one: hi

Adding an equals sign will print the variable name as well (which is useful for debugging):

foo = 81
bar = 'hello'
print(f'First argument: {foo=}, second one: {bar=}')
## First argument: foo=81, second one: bar='hello'

For simple variables, an f-string is identical to just printing two things side-by-side:

answer = 10
# A normal string literal
print('The answer is', answer)
# An f-string
print(f'The answer is {answer}')
## The answer is 10
## The answer is 10

However, for more complicated examples, f-strings will start to get more convenient than just printing. Let’s take a closer look at how to use them:

2 Formatting Numbers

If you print a number using an f-string without any formatting it might not always look good:

answer = 1/3
print(f'Very long answer: {answer}')
## Very long answer: 0.3333333333333333

To fix this, you’ll first need to choose a number format followed by width and decimal place options:

2.1 Number Formats

A first step to having better-looking numerical outputs is to format your numbers using one of the following built-in options:

  • Decimal (d): can only be used when your variable is a whole number
  • Fixed-point (f): show the decimal point in your number
  • Exponential (e): put the number into exponential notation: have one digit before the decimal point then specify how many powers of ten to multiply it by
  • General (g): either fixed-point (f) or exponential (e) format will be used - whichever Python thinks is more appropriate - and trailing zeros will get removed
  • Percentage (%): multiplies your variable by 100 and adds a percent sign

A formatting option is used by placing a colon immediately after the variable name followed by the character corresponding to your chosen option:

answer = 123
print(f'd = decimal:     {answer:d}')
answer = 123.123
print(f'f = fixed-point: {answer:f}')
print(f'e = exponential: {answer:e}')
print(f'g = general:     {answer:g}')
print(f'% = percentage:  {answer:%}')
## d = decimal:     123
## f = fixed-point: 123.123000
## e = exponential: 1.231230e+02
## g = general:     123.123
## % = percentage:  12312.300000%

2.2 Number Widths

The width of a number, ie how many characters-worth of space it takes up, is specified by placing a number between the colon and the formatting option.

  • The width of a number is equal to its number of digits, plus any decimal point/exponential sign/percent sign/etc it has, plus any white space on either side of it
  • You cannot specify a width that is smaller than the minimum amount of space needed to display a number. If you do, Python will use the minimum needed width.
  • If you specify a width that is larger than what the number needs, Python will fill up the extra space with white space (padding)
answer = 123
print(f'd = decimal:     |{answer:1d}|{answer:9d}|{answer:15d}|')
answer = 123.123
print(f'f = fixed-point: |{answer:1f}|{answer:9f}|{answer:15f}|')
print(f'e = exponential: |{answer:1e}|{answer:9e}|{answer:15e}|')
print(f'g = general:     |{answer:1g}|{answer:9g}|{answer:15g}|')
print(f'% = percentage:  |{answer:1%}|{answer:9%}|{answer:15%}|')
## d = decimal:     |123|      123|            123|
## f = fixed-point: |123.123000|123.123000|     123.123000|
## e = exponential: |1.231230e+02|1.231230e+02|   1.231230e+02|
## g = general:     |123.123|  123.123|        123.123|
## % = percentage:  |12312.300000%|12312.300000%|  12312.300000%|

2.3 Decimal Places

The number of digits that get displayed after the decimal point can be specified by placing a full stop and the desired number between the width and the format options:

answer = 123.123
print(f'f = fixed-point: |{answer:15.1f}|{answer:15.3f}|{answer:15.5f}|')
print(f'e = exponential: |{answer:15.1e}|{answer:15.3e}|{answer:15.5e}|')
print(f'g = general:     |{answer:15.1g}|{answer:15.3g}|{answer:15.5g}|')
print(f'% = percentage:  |{answer:15.1%}|{answer:15.3%}|{answer:15.5%}|')
## f = fixed-point: |          123.1|        123.123|      123.12300|
## e = exponential: |        1.2e+02|      1.231e+02|    1.23123e+02|
## g = general:     |          1e+02|            123|         123.12|
## % = percentage:  |       12312.3%|     12312.300%|   12312.30000%|

For obvious reasons, the decimal place modifier cannot be used with the “d” formatting option. Similarly, specifying more decimal places than the width will allow will be corrected by Python.

Fully format a numerical f-string with: {VariableName:Width.DecimalsFormat}

2.4 Signed Numbers

Usually, negative numbers are shown like this:

answer = -123
print(f'd = decimal:     |{answer:15d}|')
answer = -123.123
print(f'f = fixed-point: |{answer:15.1f}|{answer:15.3f}|{answer:15.5f}|')
print(f'e = exponential: |{answer:15.1e}|{answer:15.3e}|{answer:15.5e}|')
print(f'g = general:     |{answer:15.1g}|{answer:15.3g}|{answer:15.5g}|')
print(f'% = percentage:  |{answer:15.1%}|{answer:15.3%}|{answer:15.5%}|')
## d = decimal:     |           -123|
## f = fixed-point: |         -123.1|       -123.123|     -123.12300|
## e = exponential: |       -1.2e+02|     -1.231e+02|   -1.23123e+02|
## g = general:     |         -1e+02|           -123|        -123.12|
## % = percentage:  |      -12312.3%|    -12312.300%|  -12312.30000%|

To force the padding to be applied after the minus sign, prepend an equals sign to the formatting modifier:

answer = -123
print(f'd = decimal:     |{answer:=15d}|')
answer = -123.123
print(f'f = fixed-point: |{answer:=15.1f}|{answer:=15.3f}|{answer:=15.5f}|')
print(f'e = exponential: |{answer:=15.1e}|{answer:=15.3e}|{answer:=15.5e}|')
print(f'g = general:     |{answer:=15.1g}|{answer:=15.3g}|{answer:=15.5g}|')
print(f'% = percentage:  |{answer:=15.1%}|{answer:=15.3%}|{answer:=15.5%}|')
## d = decimal:     |-           123|
## f = fixed-point: |-         123.1|-       123.123|-     123.12300|
## e = exponential: |-       1.2e+02|-     1.231e+02|-   1.23123e+02|
## g = general:     |-         1e+02|-           123|-        123.12|
## % = percentage:  |-      12312.3%|-    12312.300%|-  12312.30000%|

To show a sign regardless of whether the number is positive or negative, use the plus sign:

answer = -123
print(f'd = decimal:     |{answer:+15d}|')
answer = 123.123
print(f'f = fixed-point: |{answer:+15.1f}|{answer:+15.3f}|{answer:+15.5f}|')
print(f'e = exponential: |{answer:+15.1e}|{answer:+15.3e}|{answer:+15.5e}|')
print(f'g = general:     |{answer:+15.1g}|{answer:+15.3g}|{answer:+15.5g}|')
print(f'% = percentage:  |{answer:+15.1%}|{answer:+15.3%}|{answer:+15.5%}|')
## d = decimal:     |           -123|
## f = fixed-point: |         +123.1|       +123.123|     +123.12300|
## e = exponential: |       +1.2e+02|     +1.231e+02|   +1.23123e+02|
## g = general:     |         +1e+02|           +123|        +123.12|
## % = percentage:  |      +12312.3%|    +12312.300%|  +12312.30000%|

To combine the above two and show the padding after the positive/negative sign, regardless of whether the number is positive or negative, use both an equals sign and a plus sign:

answer = -123
print(f'd = decimal:     |{answer:=+15d}|')
answer = 123.123
print(f'f = fixed-point: |{answer:=+15.1f}|{answer:=+15.3f}|{answer:=+15.5f}|')
print(f'e = exponential: |{answer:=+15.1e}|{answer:=+15.3e}|{answer:=+15.5e}|')
print(f'g = general:     |{answer:=+15.1g}|{answer:=+15.3g}|{answer:=+15.5g}|')
print(f'% = percentage:  |{answer:=+15.1%}|{answer:=+15.3%}|{answer:=+15.5%}|')
## d = decimal:     |-           123|
## f = fixed-point: |+         123.1|+       123.123|+     123.12300|
## e = exponential: |+       1.2e+02|+     1.231e+02|+   1.23123e+02|
## g = general:     |+         1e+02|+           123|+        123.12|
## % = percentage:  |+      12312.3%|+    12312.300%|+  12312.30000%|

2.5 Additional Formatting

Show leading zeros by prepending 0 to the formatting modifier:

answer = 123
print(f'd = decimal:     |{answer:015d}|')
answer = 123.123
print(f'f = fixed-point: |{answer:015.1f}|{answer:015.3f}|{answer:015.5f}|')
print(f'e = exponential: |{answer:015.1e}|{answer:015.3e}|{answer:015.5e}|')
print(f'g = general:     |{answer:015.1g}|{answer:015.3g}|{answer:015.5g}|')
print(f'% = percentage:  |{answer:015.1%}|{answer:015.3%}|{answer:015.5%}|')
## d = decimal:     |000000000000123|
## f = fixed-point: |0000000000123.1|00000000123.123|000000123.12300|
## e = exponential: |000000001.2e+02|0000001.231e+02|00001.23123e+02|
## g = general:     |00000000001e+02|000000000000123|000000000123.12|
## % = percentage:  |000000012312.3%|0000012312.300%|00012312.30000%|

Have a thousands separator by using a comma in the formatting modifier:

answer = 123456789.123
print(f'Thousands separator: |{answer:,.2f}|')
## Thousands separator: |123,456,789.12|

3 Formatting Strings

Strings are handled similarly to numbers, although they are less complex. Strings are indicated with the “s” formatting option:

first = 'Hello'
second = 'World'
print(f'Simple: |{first:s}|{second:s}|')
## Simple: |Hello|World|

Specifying a width can create padding (note that strings are left-aligned by default, whereas numbers are right-aligned):

print(f'Padding: |{first:20s}|{second:10s}|')
## Padding: |Hello               |World     |

Specifying a ‘precision’ will truncate the string:

print(f'Truncating: |{first:.2s}|{second:.3s}|')
## Truncating: |He|Wor|

Of course, truncating and padding can be combined:

print(f'Truncating & padding: |{first:15.2s}|{second:10.3s}|')
## Truncating & padding: |He             |Wor       |

3.1 Converting to Strings

A number can always be converted to a string using the str() function. There may be some circumstances where that helps you with formatting:

answer = 1234
print(f'A number: {str(answer)}')
## A number: 1234

However, this conversion from number to string can actually be done automatically by an f-string using “!s”:

print(f'Call str() using !s:               |{answer!s}|')
print(f'Call str() using !s, with padding: |{answer!s:6}|')
## Call str() using !s:               |1234|
## Call str() using !s, with padding: |1234  |

This works for Booleans too:

first = True
second = False
print(f'Call str() on Booleans: |{first!s:8}|{second!s:8}|')
## Call str() on Booleans: |True    |False   |

4 Formatting Dates

Things such as datetime objects can also be formatted within the curly brackets of an f-string. Here’s an example of a normal (unformatted) datetime object (more info about these can be found on the Date and Time page):

from datetime import datetime

dt = datetime(2012, 3, 4, 5, 6, 7)

print(dt)
## 2012-03-04 05:06:07

These can be formatted by adding a date format code as a string after the colon:

dt = datetime(2012, 3, 4, 5, 6, 7)

print(f'{dt:%Hh%M on %d %B %Y}')
## 05h06 on 04 March 2012

For more info about date format codes, see the documentation here.

5 Alignment

By default, strings get left-aligned and numbers get right-aligned. This can be controlled explicitly by using the “<”, “>” and “^” characters:

first = 'String'
second = 123.456
print(f'Default: |{first:16s}|{second:16.2f}|')
print(f'Left:    |{first:<16s}|{second:<16.2f}|')
print(f'Right:   |{first:>16s}|{second:>16.2f}|')
print(f'Centred: |{first:^16s}|{second:^16.2f}|')
## Default: |String          |          123.46|
## Left:    |String          |123.46          |
## Right:   |          String|          123.46|
## Centred: |     String     |     123.46     |

6 Lists

You can format an entire list of objects by using a combination of f-strings, list comprehension and the .join() method:

ls = [
    6.28318,
    2.71828,
    0.57721,
    9.81,
    6.67430,
]
# The formatter ".0f" will round to the nearest whole number
print('\n'.join(f'{v:.0f}' for v in ls))
## 6
## 3
## 1
## 10
## 7

7 Cheat Sheet

The general form of a standard format specifier is:

[[fill]align][sign][#][0][width][,][.precision][type]

Take a look at the explanatory table below or here for more details.

Field Description Values Default
fill What character to fill ‘white space’ padding with Any character Space
align Align the object left, right or centrally “<”, “>”, “=”, “^” “<” (strings), “>” (numbers)
sign How positives, negatives, bases and thousands get treated “+”, “-”, " “,”#“,”," “-”
width The minimum field width Any positive integer The variable’s width
precision How many digits should be displayed after the decimal point/how long the string must be Any positive integer The precision of the number/length of the string
type How the data should be presented “b”, “c”, “d”, “e”, “E”, “f”, “F”, “g”, “G”, “n”, “o”, “s”, “x”, “X”, “%” “s”, “d”, “g”

⇦ Back