Formatting f-strings on Python

A detailed beginner’s guide — with examples!

Luke Liu
10 min readJan 19, 2021

After doing a ton of research when I needed to use it, I couldn’t find many resources on using f-strings to make fast, efficient, and attractive outputs on Python. So without further ado, here is my quick beginner’s guide to using f-strings.

You can ctrl+f through this guide to find the part you need, or use the handy table of contents below:

  1. The Basics of f-strings
  2. Formatting
  3. Data Types and Notations
  4. Detailed Examples (and usage scenarios)
  5. Cheat Tables
  6. Credits

Skipping all of the what are f-strings and why are f-strings better material which you can find all over the internet, I will dive straight into the parameters of the f-string and how you can use them to format your outputs.

The Basics of f-strings

Here, I will quickly talk about the very basics of using f-strings to print integers, floats, operations, variables, etc.

Let’s say you had variables first name, last name, and you wanted to print the simple sentence, “Hi, my name is <first name> <last name>, what about you?”.

Before, you would have to do that by exiting your string’s quotation, making a plus (+) sandwich with the variable(s), and re-entering into your string’s quotation to add the punctuation.

With f-strings, all you have to do is put an “f” at the front of your print string, and use curly braces with the variable name ({<var name>}) right in the middle of your string. None of that messy in and out stuff!

first_name = 'Keanu' 
last_name = 'Reeves'
# Old way (gross)print('Hi, my name is '+ first_name + last_name + ', what about you?')>>> Hi, my name is Keanu Reeves, what about you?# With f string :^)print(f'Hi, my name is {first_name} {last_name}, what about you?')>>> Hi, my name is Keanu Reeves, what about you?# Look how much cleaner it is!

You can also do this with integers and operations:

integer = 9
float = 2.22
print(f'The number {integer} multiplied by the number {float} is: {integer*float}'>>> The number 9 multiplied by the number 2.22 is 19.98.

As well as lists and dictionaries (please note the importance of using a different type of quotation than the one you used for the list/dictionary):

# Using a list:
colour_list = ["red", "purple", "green"]
print(f'There are {len(colour_list)} colours in this list. One of them is {colour_list[1]}.')>>> There are 3 colours in this list. One of them is purple.
# Using a dictionary:
name_dict = {"first": "Stephen", "last": "Curry"}
print(f'My favourite basketball player is {name_dict["first"]} {name_dict["last"]}.')>>> My favourite basketball player is Stephen Curry.

These are obviously very simple examples and you can do much more complicated versions of these, but I am keeping them simple for the sake of explanation.

Finally, you can also use functions with these.

num_list = [1, 2, 3]def add_one(num):
return num + 1
print(f'{[add_one(num) for num in num_list]}')>>> [2, 3, 4]

You can also use f-strings with classes and objects (and much more), but I won’t go into that in this guide.

Formatting

Now that we’ve covered the very basics, let’s start formatting to make pretty outputs! The f-strings come with many different formatting options which you can include within the curly braces to produce different types of outputs, with many different combinations.

Once you are familiar with how to apply these, feel free to use the charts from Bentley University’s documentation which I included at the bottom.

The following follows the format of: {<var>:<specification>}. For example, {number: >10,.2f} which means a number right aligned with 10 spaces in the middle, split by commas at every thousand, and followed by 2 decimals. Don’t worry, you will understand it shortly. Adding a space between the colon and the specification adds an extra space in some cases.

Alignment

There are four main ways to align your f-string texts. They are left, right, and center alignments, as well as padding between sign and digit. I will elaborate more on these alignments, as well as provide many examples of them.

Left Align (<) can be used as the name implies — to align the text within the available space to its left. This is the default setting in most cases, so I will not be including an example here (because it will look the same).

Right Align (>) is used to align the text within the available space to its right. From what I found, typing > alone makes no difference — the default value seems to be 1 (length of a space). Typing >5 puts a total distance of five plus one (default) spaces between the two texts. Since this is a total, if it is a 3 digit number, there will be 5+1–3 = 3 visible spaces. In general, I found that there will be n+1–(# of digits) visible spaces. Signs (–,+) take up a space.

# I do this example using ints, but the same applies with strings.num = 1
num_2 = -22
num_3 = 333
print(f'1. This is the default spacing: {num:>}')
# If I did not include the space there, it would have no spaces.
print(f'2. This will be right aligned 5 spaces: {num:>5}')
print(f'3. This will be right aligned 5 spaces: {num_2:>5}')
print(f'4. This will be right aligned 5 spaces: {num_3:>5}')
>>> 1. This is the default spacing: 1
>>> 2. This will be right aligned 5 spaces: 1
>>> 3. This will be right aligned 5 spaces: -22
>>> 4. This will be right aligned 5 spaces: 333
# By highlighting and counting, you can see the number of spaces

Padding (=) can be used for numeric types only. This adds space padding between the sign (if there are any) and the digits. Similarly to the previous right alignment, this is a total space. In general, there will be n–(1 if there is a sign)–(# of chars). This will be shown in the following example. It seems to have a default value of 0. If there is no sign, this will function similar to having a right alignment of n. Signs (–,+) take up a space.

num = 1
num_2 = 123
neg = -1
neg_2 = -123
print(f'1. This is the default: {num:=}')
print(f'2. This is the default: {neg_2:=}')
print(f'3. This adds 7 spaces between sign and digit: {num:=7}')
print(f'4. This adds 7 spaces between sign and digit: {neg:=7}')
print(f'5. This adds 7 spaces between sign and digit: {num_2:=7}')
print(f'6. This adds 7 spaces between sign and digit: {neg_2:=7}')
print(f'7. This fills the space with asterisks between sign and digit: {neg_2:>=7}')
>>> 1. This is the default: 1
>>> 2. This is the default: -123
>>> 3. This adds 7 spaces between sign and digit: 1
>>> 4. This adds 7 spaces between sign and digit: - 1
>>> 5. This adds 7 spaces between sign and digit: 123
>>> 6. This adds 7 spaces between sign and digit: - 123
>>> This fills the space with asterisks between sign and digit: -***123

Center Alignment (^) will center your text in the space available. Once again, this is a total and the number of visible spaces will be n+1–(# of chars). The default is no center alignment. The center alignment may appear lopsided or uneven depending on whether or not the value has Signs (–,+) take up a space.

# This example was done with numbers but works with strings as well.num = 1
num_2 = 123
neg = -1
neg_2 = -123
# I have added a '|' to the following outputs to signify the end of # the center alignment.print(f'1. This is the default: {num:^}|')
print(f'2. This is the default: {neg_2:^}|')
print(f'3. This center aligns with 9 spaces: {num:^9}|')
print(f'4. This center aligns with 9 spaces: {neg:^9}|')
print(f'5. This center aligns with 9 spaces: {num_2:^9}|')
print(f'6. This center aligns with 9 spaces: {neg_2:^9}|')
print(f'7. This center aligns with 8 spaces: {num_2:^8}|')>>> 1. This is the default: 1|
>>> 2. This is the default: -123|
>>> 3. This center aligns with 9 spaces: 1 |
>>> 4. This center aligns with 9 spaces: -1 |
>>> 5. This center aligns with 9 spaces: 123 |
>>> 6. This center aligns with 9 spaces: -123 |
>>> 7. This center aligns with 8 spaces: 123 |

This concludes alignments. To summarize:

  • Typically n+1–(# of chars) visible spaces.
  • Signs take up a space (one less visible space).
  • Default is usually like not specifying a parameter at all.

I will now continue on to explain the different data types.

Data Types and Notations

There are seven main data types and notations for f-strings. String, decimal integers, numbers, exponent, fixed-point, and percentage. These are their explanations and examples. I’ll start with the ones that made a noticeable difference with the output.

Exponent (e) notation is simple enough — it takes the specific number and displays it in scientific notation, with e indicating the exponent, and defaulting at precision 6.

num = 3.14159265
num_2 = 1000
num_3 = 0.001
neg = -20.00
print(f'1. This is the default: {num}')
print(f'2. This is the default: {num_2}')
print(f'3. This is the default: {num_3}')
print(f'4. This is the default: {neg}')
print(f'5. This is sci-not with default precision {num:e}')
print(f'6. This is sci-not with default precision: {num_2:e}')
print(f'7. This is sci-not with default precision: {num_3:e}')
print(f'8. This is sci-not with default precision: {neg}')
print(f'9. This is sci-not with precision 3: {num:.3e}')
print(f'10. This is sci-not with precision 3: {num_2:.3e}')
print(f'11. This is sci-not with precision 3: {num_3:.3e}')
print(f'12. This is sci-not with precision 3: {neg:.3e}')
>>> 1. This is the default: 3.14159265
>>> 2. This is the default: 1000
>>> 3. This is the default: 0.001
>>> 4. This is the default: -20.0
>>> 5. This is fixed-point with default precision: 3.141593e+00
>>> 6. This is fixed-point with default precision: 1.000000e+03
>>> 7. This is fixed-point with default precision: 1.000000e-03
>>> 8. This is fixed-point with default precision: -2.000000e+01
>>> 9. This is fixed-point with precision 3: 3.142e+00
>>> 10. This is fixed-point with precision 3: 1.000e+03
>>> 11. This is fixed-point with precision 3: 1.000e-03
>>> 12. This is fixed-point with precision 3: -2.000e+01

Fixed-point (f) notation is a representation of the number with added or removed decimal places depending on the inputted precision. Defaulting at 6, the precision can be changed just like (e).

num = 3.14159265
num_2 = 1000
num_3 = 0.001
neg = -20.00
print(f'1. This is the default: {num}')
print(f'2. This is the default: {num_2}')
print(f'3. This is the default: {num_3}')
print(f'4. This is the default: {neg}')
print(f'5. This is fixed-point with default precision: {num:f}')
print(f'6. This is fixed-point with default precision: {num_2:f}')
print(f'7. This is fixed-point with default precision: {num_3:f}')
print(f'8. This is fixed-point with default precision: {neg:f}')
print(f'9. This is fixed-point with precision 3: {num:.3f}')
print(f'10. This is fixed-point with precision 3: {num_2:.3f}')
print(f'11. This is fixed-point with precision 3: {num_3:.3f}')
print(f'12. This is fixed-point with precision 3: {neg:.3f}')
>>> 1. This is the default: 3.14159265
>>> 2. This is the default: 1000
>>> 3. This is the default: 0.001
>>> 4. This is the default: -20.0
>>> 5. This is fixed-point with default precision: 3.141593
>>> 6. This is fixed-point with default precision: 1000.000000
>>> 7. This is fixed-point with default precision: 0.001000
>>> 8. This is fixed-point with default precision: -20.000000
>>> 9. This is fixed-point with precision 3: 3.142
>>> 10. This is fixed-point with precision 3: 1000.000
>>> 11. This is fixed-point with precision 3: 0.001
>>> 12. This is fixed-point with precision 3: -20.000

Percentage (%) display will output the value as a percentage. Take note that it does convert a decimal into a percentage (i.e, 0.81 will become 81%). The precision defaults to 6 as well, similar to (e) and (f).

num = 3.14159265
num_2 = 1000
num_3 = 0.001
neg = -20.00
print(f'1. This is the default: {num}')
print(f'2. This is the default: {num_2}')
print(f'3. This is the default: {num_3}')
print(f'4. This is the default: {neg}')
print(f'5. This is fixed-point with default precision: {num:%}')
print(f'6. This is fixed-point with default precision: {num_2:%}')
print(f'7. This is fixed-point with default precision: {num_3:%}')
print(f'8. This is fixed-point with default precision: {neg:%}')
print(f'9. This is fixed-point with precision 3: {num:.3%}')
print(f'10. This is fixed-point with precision 3: {num_2:.3%}')
print(f'11. This is fixed-point with precision 3: {num_3:.3%}')
print(f'12. This is fixed-point with precision 3: {neg:.3%}')
>>> 1. This is the default: 3.14159265
>>> 2. This is the default: 1000
>>> 3. This is the default: 0.001
>>> 4. This is the default: -20.0
>>> 5. This is fixed-point with default precision: 314.159265%
>>> 6. This is fixed-point with default precision: 100000.000000%
>>> 7. This is fixed-point with default precision: 0.100000%
>>> 8. This is fixed-point with default precision: -2000.000000%
>>> 9. This is fixed-point with precision 3: 314.159%
>>> 10. This is fixed-point with precision 3: 100000.000%
>>> 11. This is fixed-point with precision 3: 0.100%
>>> 12. This is fixed-point with precision 3: -2000.000%

String (s) format is the default representation for strings. As far as I could tell, this does not make a difference to your output and often presents an error, so just disregard it.

Decimal Integer (d) will output the value as a base-10 number. Not exactly sure how this works. It doesn’t convert from other bases, nor does it really change anything from what I could tell. If you know, please let me know!

Number (n) will “insert the appropriate number of separator characters” based on your locale setting. After playing around with it, I didn’t notice any differences between including it or not.

Detailed Examples (and usage scenarios)

Here, I’ll try to provide some detailed usage scenarios demonstrating a combination of the previously explained data types and formatting. So far, I only have one super simple example as it’s pretty hectic right now — leave a comment of what kind of example you want to see, and I will post it as soon as I can!

Simple Percentages:

def simple_percentages(num_1, num_2, operation):
if operation == "percentage":
print(f"{num_1} divided by {num_2} is {num_1/num_2:.0%}
# Output of simple_percentages(1, 2, "percentage")
>>> 50%

Cheat Tables

Table for Alignment
Table for Data Types

Again, these tables were from the Bentley University’s documentation.

Credits

I get the formatting specification information from Bentley University’s documentation of f-string formatting here. This is the only documentation I was able to find on the front page of Google which gives information on how to format f-strings beyond one line outputs. I put it in a more beginner-friendly way, as well as include more examples of how they can be combined to produce different outputs.

--

--