Python F-String Codes I Use Every Day

By on 5 April 2024


A few examples that will save the day probably* 95% of time.

*I don’t have the actual data but seriously, I bet you’ll find those tips useful more often than not!


Introduction

This article was originally posted on Medium.

I use f-strings every day. The irony is I also every day end up searching the Web to find the correct format to use. Until one day I thought a better use of my time would be to create a cheat sheet of the most common formatting cases — AKA this article. It covers the following:

  • integers, floats, numbers and scientific notation
  • percentages %
  • dates
  • padding
  • adding +/- sign in front of a number

It’s important to note that the f-strings were first introduced in Python 3.6 (PEP 498 if you REALLY must know) so make sure to check the Python version first, if things don’t work for you.


The format

The most basic f-string format goes like this:

SmkAAj4o.jpg large

You can use this format to print numbers, texts, or even evaluate expressions.

author = "pawjast"
year = 2022

print(f"Example 1: {author}") # string
print(f"Example 2: {year}") # number
print(f"Example 3: {2 + 2}") # expression

The output:

Example 1: pawjast
Example 2: 2022
Example 3: 4

You might have noticed that the 2+2 expression in Example 3 got evaluated and 4 was printed.

You’ll get both, the name and the value if you add = sign to a variable.

text = "Data Science Blog"

print(f"{text=}")

The output:

text='Data Science Blog'

Template below generalizes how you can add a specific format to a variable:

t9JnTpBB.jpg large

Next paragraphs shows examples of how to use it.


Recap on numbers

Last stop before going any further. I’ll be using different ways of writing numbers later in the article so let’s review the most common ones.

int_1 = 1
int_with_separator = 1_000  # `int` with 1,000 separator
float_1 = 1.125
float_2 = 3.50
scientific_1 = 1.23e2  # 1.23 * 10^2

print(f"Example 1 - int: {int_1}")
print(f"Example 2 - int with _ as thousands separator: {int_with_separator}")
print(f"Example 3 - float: {float_1}")
print(f"Example 4 - float with trailing zero: {float_2}")
print(f"Example 5 - float in scientific notation: {scientific_1}")

The output:

Example 1 - int: 1
Example 2 - int with _ as thousands separator: 1000
Example 3 - float: 1.125
Example 4 - float with trailing zero: 3.5
Example 5 - float in scientific notation: 123.0

You can observe that:

  • floats had the trailing zeros truncated (Example 4)
  • scientific notation was printed as a regular float
  • the rest of the variables were printed “as is”

Floats

The float type is enforced by using code f. What you want to control in floats is the number of decimal places.

pi_val = 3.141592

print(f"Example 1: {pi_val:f}")
print(f"Example 2: {pi_val:.0f}")
print(f"Example 3: {pi_val:.1f}")
print(f"Example 4: {pi_val:.3f}")

The output:

Example 1: 3.141592
Example 2: 3
Example 3: 3.1
Example 4: 3.142

💡 Side notef-strings are flexible enough to allow nesting.

float_val = 1.5
precision = 3

print(f"{float_val:.{precision}f}")

The output:

1.500

Percentage

Use code % to enforce percentage type. Percentage is still a float so you can still use .<whole_number> to control the precision.

val = 0.5

print(f"Example 1: {val:%}")
print(f"Example 2: {val:.0%}")

The output:

Example 1: 50.000000%
Example 2: 50%

More examples of controlling precision in %:

val = 1.255

print(f"Example 1: {val:.0%}")
print(f"Example 2: {val:.1%}")

The output:

Example 1: 125%
Example 2: 125.5%

Scientific notation

If you want scientific notation to be printed as such (and not as a regular float) it can be enforced with e or E code.

val = 1.23e3  # 1.23 * 10^3

print(f"Example 1: {val:e}")
print(f"Example 2: {val:E}")

The output:

1: 1.230000e+03
2: 1.230000E+03

No surprise the precision can be controlled in this case too.

val = 1.2345e3

print(f"{val:.2e}")

The output:

1.23e+03

You can even print a regular number in scientific notation.

val = 2022

print(f"{val:.3e}")

The output:

2.022e+03

Integers

Integers are enforced using code d.

val = 1

print(f"{val:d}")

The output:

1

Adding , to the code will print the thousands separator.

int_1 = 1000
int_2 = 1000_000_000

print(f"{int_1:,d}")
print(f"{int_2:,d}")

The output:

1,000
1,000,000,000

Numbers

If the aim is to just print a number, you can use generic code — n.

val_int = 1
val_float = 1.234
val_scient = 4.567e2

print(f"{val_int =: n}")
print(f"{val_float =: n}")
print(f"{val_scient =: n}")

The output:

val_int = 1
val_float = 1.234
val_scient = 456.7

You can still use .<whole_number> format to control the precision.

💡 Side note: in this case whole_number determines the total number of digits printed, not the number of decimal points! On top of that, n code will decide the best output format for a number.

val_float_1 = 1.234
val_float_2 = 20.234
val_float_3 = 123.456

print(f"{val_float_1 =: .2n}")  # prints as truncated float
print(f"{val_float_2 =: .2n}")  # prints as int
print(f"{val_float_3 =: .2n}")  # prints as scientific notation

The output:

val_float_1 = 1.2
val_float_2 = 20
val_float_3 = 1.2e+02

Dates

from datetime import date, datetime

Printing a date “as is” works exactly like printing any other variable.

day = date(
    year=2022,
    month=9,
    day=1
)

print(f"{day}")

The output:

2022-09-01

To recreate the format you will use the following codes:

  • %Y for year
  • %m for month
  • %d for day

With those codes you can e.g. create a new date format.

print(f"{day:%Y-%m-%d}")  # default appearance
print(f"{day:%Y/%m/%d}")  # use `/` as separator

The output:

2022-09-01
2022/09/01

It’s also possible to print a month as a text:

  • %b — short version
  • %B — long version
print(f"{day:%Y %b %d}")
print(f"{day:%Y %B %d}")

The output:

2022 Sep 01
2022 September 01

The same variable can be printed multiple times.

print(f"{day:%b or %B}?")
print(f"{day:%Y %Y %Y}"

The output:

Sep or September?
2022 2022 2022

Reusing the same variable can be useful e.g. when you want to print the date and provide the day of the week as text (using code %A ).

print(f"{day:%Y %b %d (%A)}")

The outcome:

2022 Sep 01 (Thursday)

Last but not least, you can swap %Y for %y to get short version of the year.

print(f"{day:%y.%m.%d}")

The output:

22.09.01

Datetime

Let’s specify two datetime variables.

day_and_time = datetime(
    year=2022,
    month=9,
    day=1,
    hour=17,
    minute=30,
    second=45
)
now = datetime.now()

print(f"{day_and_time}")
print(f"{now}")  # with mircoseconds

The output:

2022-09-01 17:30:45
2022-12-08 15:49:37.810347

Time format requires the following codes:

  • %H — hour
  • %M — minute
  • %S — second
  • %f — millisecond (1s = 1000 milliseconds)

Therefore, the default format would look like below.

print(f"{now:%Y-%m-%d %H:%M:%S.%f}")

The outcome:

2022-12-08 15:49:37.810347

f-string obviously creates a string (try this code to confirm it: type(f”now:%Y-%m-%d %H:%M%S.%f}”)). Therefore, if e.g. you are not happy with the number of decimal points for milliseconds, you can easily truncate them.

print(f"{now:%Y-%m-%d %H:%M:%S.%f}"[:22])

The output:

2022-12-08 15:49:37.81

In order to change the 24hr format to 12hr format, you will need to:

  • swap hour code from %H to %I
  • Optionally add %p at the end if you want to add AM/PM to the time
print(f"24hr: {day_and_time:%Y-%m-%d %H:%M:%S}")
print(f"12hr: {day_and_time:%Y-%m-%d %I:%M:%S}")
print(f"12hr with AM/PM: {day_and_time:%Y-%m-%d %I:%M:%S %p}")

The output:

24hr: 2022-09-01 17:30:45
12hr: 2022-09-01 05:30:45
12hr with AM/PM: 2022-09-01 05:30:45 PM

Few more useful date formats:

  • %j for day of the year
  • %W for week of the year (assuming Monday as first day of the week)
  • %U for week of the year (assuming Sunday as first day of the week
day = date(
    year=2018,
    month=9,
    day=17
)

print(f"The date: {day}")
print(f"Day of the year: {day: %j}")
print(f"Week of the year (Mon): {day: %W}")
print(f"Week of the year (Sun): {day: %U}")

The outcome:

The date: 2018-09-17
Day of the year:  260
Week of the year (Mon):  38
Week of the year (Sun):  37

Padding

Padding with empty spaces.

val = 1

print(f"1: {val:1d}")
print(f"2: {val:2d}")
print(f"3: {val:3d}")

The output:

1: 1
2:  1
3:   1

Padding with zeros.

val = 1

print(f"1: {val:01d}")
print(f"2: {val:02d}")
print(f"3: {val:03d}")

The output:

1: 1
2: 01
3: 001

I usually use zero — padding with for loop to keep the text nicely aligned in the terminal.

for i in range(11):
    print(f"{i:02d}")

The output:

01
02

...


09
10

Positive/negative sign

In some cases you will require to show a +/- sign next to a number.

positive = 1.23
negative = -1.23

print(f"1: {positive:+.2f}   {negative:+.2f}")
print(f"2: {positive:-.2f}   {negative:-.2f}")
print(f"3: {positive: .2f}   {negative: .2f}")

The output:

1: +1.23   -1.23
2: 1.23   -1.23
3:  1.23   -1.23

Combining all things together

# print variable with name, limit precision and thousands separator
val = 11500.23456

print(f"{val = :,.3f}")

The output:

val = 11,500.235

We’re done 🎉.


Full code

🔗 GitHub notebook


Connect with me

💬 Medium ◽ Twitter / X ◽ GitHub ◽ Substack ◽ LinkedIn


Resources

1️⃣ https://docs.python.org/3/reference/lexical_analysis.html#f-strings

2️⃣ https://docs.python.org/3/library/string.html#format-specification-mini-language

3️⃣ https://strftime.org/

Want a career as a Python Developer but not sure where to start?