3 Useful Python F-string Tricks You Probably Don’t Know

String
Photo by amirali mirhashemian / Unsplash

Long gone are the days when Python developers used the % operator to perform string formatting in Python.

Sometime later down the road when Python 3.0 was introduced, common use of the % the operator was gradually replaced with calling the .format() method on the String object.

Fast forward to Python 3.6 and beyond, f-string was introduced as a new way to embed Python expression inside our string constants. Today, many have already adopted this change.

A brief overview of string formatting in Python
A brief overview of string formatting in Python. (Made using: https://carbon.now.sh/)

For those who are unfamiliar with this, using f-string in Python is super simple. Simply prefix your string with an f or F and then followed by single, double, or even triple quotes to create your string, e.g., f"Hello, Python!".

While most of you might already be familiar with f-string formatting in Python, today I am going to demonstrate some of the lesser-known tricks of using f-string in Python 3.8+.

Topics covered:

  • Using f-string for better debugging
  • Format float decimal places, currency, datetime objects, and padding with f-string
  • Using f-string for conversions (ASCII and repr())

Let’s dive in, shall we?


F-string for Debugging

As developers, we often find ourselves using print statements to debug our code simply because they are easy to add.

Chances are, we’ll do something like this:

viewer = "🐊"
owner = "🐼"
editor = "🐓"

print(viewer)
print(owner)
print(editor)
A good way to lose track of which value belongs to which variable.

Here’s the output printed on our terminal:

🐊
🐼
🐓
Terminal output.

Honestly, there’s nothing wrong with printing using the code above.

However, while staring at a terminal full of other debugger logs, one might easily forget the order of the variable printed out. In such a use case, debugging with print statements can quickly turn into finding a needle in a haystack. In our case:

🐊
🐼 -- Sorry, which variable does this belong to again?
🐓
A better way to print variables during debug.

To cope with this, we can do print(f’{variable_name=}’) instead.

print(f"{viewer=}")
print(f"{owner=}")
print(f"{editor=}")

# Stdout:

# viewer = "🐊"
# owner = "🐼"
# editor = "🐓"
A clearer way to debug print using f-string.

Even though we have to wrap our variables with the f-string syntax, everything is so much clearer. Now, we will never lose track of the order of the printed variable during debugging.

Furthermore, using f-string this way preserves whitespaces, which can be helpful during our debugging process when we are in the midst of looking at confusing terminal logs.

print(f"{viewer=     }")
print(f"{owner     =}")
print(f"{editor     =      }")

# Stdout:

# viewer=     '🐊'
# owner     ='🐼'
# editor     =      '🐓'
f-string preserves whitespaces.

String Formatting

Besides using f-string for debugging, my absolute favorite feature about f-string is its flexibility, which allows us to format our string with ease.

With f-string, it’s much easier to read, write, and maintain the output of the string with great flexibility as compared to the plain old string concatenation.

The simplest example can be demonstrated when we’re dealing with float type variables.

How to format float to N decimal places

For instance, imagine we need to print a float type variable in two decimal places, e.g., making 3.1425123 into 3.14. Not exactly an uncommon use case, right?

Typically, one might think of using the Python built-in round method to do so. Or perhaps, you’re thinking of using the “older” str.format way of doing it, such as:

# The "old" ways of updating float to 2 decimal places

float_variable = 3.141592653589793

print("%.2f" % float_variable)
print("{:.2f}".format(float_variable))

# Stdout:

# 3.14
# 3.14
Ways of limiting float to two decimal places.

What if we could use f-string to do so instead? Let’s try again!

float_variable = 3.141592653589793

print(f"{float_variable:.2f}")

# Stdout:

# 3.14
Using f-string in this scenario is so much easier than str.format()

Turn float into a pretty currency value

When you’re dealing with currency, you would need to prepare your strings to be as user-friendly as possible. For instance, it might be a better idea to format our currency value of 3142671.76 as $3,142,671.76.

In such a scenario, formatting our float value as currency using f-string is extremely handy. We can easily do this by using ,:2f.

money = 3_142_671.76 # 💡 This is the same as 3142671.76

print(f"${money:,.2f}")

# Stdout:

# $3,142,671.76
Format float type variable as a pretty-looking currency. Simple!

Pretty format datetime without strftime

Besides using it to format float type variables, we can even use f-string along with datetime type variable.

While formatting a datetime object into a more human-friendly manner, such as 05-July-2021, the most common way of doing so is to use the standard built-in strftime method of the datetime object, e.g., datetime_var.strftime(‘%d-%b-%y’).

Alternatively, we could use f-string to easily format our datetime variable. Here’s an example of what I meant:

from datetime import datetime
now = datetime.now()


# The usual way
formatted_datetime_now = now.strftime('%d-%B-%Y')
print(formatted_datetime_now)

# F-string way
formatted_datetime_now = f"{now:%d-%B-%Y}"
print(formatted_datetime_now)

# Stdout
# 05-July-2021
Formatting datetime variable with f-string instead of strftime.

Padding your int variables with leading zeroes or whitespaces

Depending on what you’re working on, there might be times where you will need to pad your integer in front while displaying or using it as a string.

Rather than having to write a custom function to zero-pad our integers, f-string allows you to zero-pad your integers without breaking a sweat. To pad with zeroes, simply do this:

# Output length of 20, and pad the rest with zeroes

int_variable = 1_234_567
print(f'{int_variable:020}')

# Stdout
# 00000000000001234567


# Output length of 24, and pad the rest with zeroes
int_variable = 30
print(f'{int_variable:024}')

# Stdout
# 000000000000000000000030
Pad your integer typed variable with leading zeroes

To pad your integers with leading whitespace:

# Output length of 10, and pad the rest with leading whitesplace
int_variable = 20_21
print(f'{int_variable:10d}')

# Stdout
# '      2021'


# Output length of 5, and pad the rest with leading whitesplace
print(f"{int_variable:5d}")

# Stdout
# ' 2021'
Pad your integer typed variable with leading whitespaces!

Conversion

In the last section of this article, I will run you through some brief examples of using f-string for conversion. When you use an exclamation mark syntax, !, followed by your variable in your f-string, it will perform extra conversion on that variable.

Convert your string to ASCII representation

For instance, you can easily print out the ASCII representation of your string with f’{your_variable!a}’, just like this:

owl = '🦉'
print(f'{owl!a}')

# Stdout

# '\U0001f989'
Shows the ASCII representation of your emoji.

A repr() alternative with f-string

Lastly, another good use of the ! syntax in f-string is to display the string containing a printable representation of our object, just like using the repr() method in Python.

Here’s an example:

from datetime import datetime


now = datetime.now()

# Using repr()
print(repr(now))


# F-string way
print(f'{now!r}')

# Stdout
# datetime.datetime(2021, 7, 5, 13, 2, 34, 672383)

repr(now) == f'{now!r}'
# True
Using !r instead of repr()

Closing Thoughts

Since the Python 3.6 era, f-string has been an amazing way to format strings in Python. Using f-strings in Python is incredibly easy, and I have been using them ever since they were introduced.

Paired with the flexibility of letting us include expressions, conditions, and even formatting in our string object, f-string is undoubtedly simple yet powerful.

My personal favorite here is to use f-string for datetime object formatting as well as formatting any currency values.

Honestly, I am beyond thrilled to see how Python has evolved over these years, gradually making our developer experience better and better. I hope you learned a lot from this article and actually put these tips into use in your side projects or codebase at work.

DigitalOcean Referral Badge