Advanced string formatting with f-strings in Python
Tags: python, beginners, tutorial, programming
Published: 2024-05-07 14:46:50

F-strings (formatted string literals) are a way to embed expressions inside string literals, introduced in Python 3.6, and provide a concise and readable syntax for [string formatting](https://byby.dev/py-string-interpolation).

Begin your string literal with either lowercase `f` or uppercase `F`. This indicates that it's an f-string. Place expressions within curly braces `{}` where you want to insert their values into the string. These can be variables, calculations, function calls, or any valid Python expression.

These expressions are evaluated at runtime, and their values are inserted into the string. Here's a basic example of how you can use f-strings for string formatting:

```py
name = "Alice"
age = 30
city = "New York"

message = f"Hello, {name}! You are {age} years old and live in {city}."

print(message)
# Hello, Alice! You are 30 years old and live in New York.
```

An optional format specifier can follow the expression. Format specifications are used within replacement fields contained within a format string to define how individual values are presented. Each formattable type may define how the format specification is to be interpreted.

## Numeric precision

The concept of numeric precision is crucial when working with floating-point numbers. You can control numeric precision through formatting options by using `:.nf` to specify the number of decimal places for a floating-point number, where `n` is an integer.

```py
price = 123.456789

# Format to two decimal places
formatted_price_2 = f"Price: ${price:.2f}"
print(formatted_price_2)  # Output: Price: $123.46

# Format to three decimal places
formatted_price_3 = f"Price (3 decimals): ${price:.3f}"
print(formatted_price_3)  # Output: Price (3 decimals): $123.457

# Format to no decimal places (integer rounding)
formatted_price_int = f"Price (rounded): ${price:.0f}"
print(formatted_price_int)  # Output: Price (rounded): $123
```

## String alignment and width

You can use `:<w`, `:>w`, or `:^w` to align a string to the left, right, or center within a given width `w`, where `w` is an integer. For example, `f"{name:>10}"` will right-align the name within 10 spaces.

```py
# Left alignment
name = "Alice"
print(f"Hello, {name:<10}!") # Output: Hello, Alice     !

# Right alignment
name = "Bob"
print(f"Hello, {name:>10}!") # Output: Hello,        Bob!

# Center alignment
name = "Charlie"
print(f"Hello, {name:^10}!") # Output: Hello,  Charlie !
```

## Type-specific formatting

You can use `:t` to apply type-specific formatting to a value, where `t` is a character that represents the type. For example, `:b` for binary, `:x` for hexadecimal, `:e` for scientific notation, `:%` for percentage, etc.

```py
# Binary format
num = 42
print(f"{num:b}") # Output: 101010

# Hexadecimal format
num = 255
print(f"{num:x}") # Output: ff

# Scientific notation format
num = 123456789
print(f"{num:e}") # Output: 1.234568e+08

# Percentage format
num = 0.75
print(f"{num:%}") # Output: 75.000000%
```

## Zero-padding numbers

You can use `:0w` to pad a number with leading zeros within a given width `w`, where `w` is an integer. For example, `f"{7:03}"` will output `007`.

```py
# Padding numbers with zeros
num = 42
print(f"The answer is {num:04}.") # Output: The answer is 0042.
```

## Date and time formatting 

In f-strings, you can use a variety of format specifiers for formatting date and time using the datetime module. These format specifiers are similar to the ones used with the `strftime` method. Here are some common date and time format specifiers:

- `%Y`: Year with century as a decimal number (e.g., 2022).
- `%y`: Year without century as a zero-padded decimal number (e.g., 22).
- `%m`: Month as a zero-padded decimal number (01, 02, ..., 12).
- `%d`: Day of the month as a zero-padded decimal number (01, 02, ..., 31).
- `%H`: Hour (00, 01, ..., 23).
- `%M`: Minute (00, 01, ..., 59).
- `%S`: Second (00, 01, ..., 59).
- `%A`: Weekday as a full name (Monday, Tuesday, ..., Sunday).
- `%a`: Weekday as an abbreviated name (Mon, Tue, ..., Sun).
- `%B`: Month as a full name (January, February, ..., December).
- `%b` or `%h`: Month as an abbreviated name (Jan, Feb, ..., Dec).
- `%p`: AM or PM.

Here's an example of using these format specifiers in f-strings:

```py
# Import the datetime module
import datetime

# Create a datetime object with the current date and time
now = datetime.datetime.now()

# Format the datetime object using f-strings and format specifiers
print(f'The current date is {now:%Y-%m-%d}.')
print(f'The current time is {now:%H:%M:%S}.')
print(f'The current date and time is {now:%Y-%m-%d %H:%M:%S}.')

# Output:
# The current date is 2024-02-13.
# The current time is 16:33:42.
# The current date and time is 2024-02-13 16:33:42.
```