String formatting¶
In this tutorial, you will master the art of string formatting in Python. You will learn how to embed expressions inside strings, control alignment and padding, and format numbers with precision.
Time commitment: 15–20 minutes
Prerequisites:
- Completion of String methods
- Understanding of basic string operations
Learning objectives¶
By the end of this tutorial, you will be able to:
- Use f-strings to embed expressions inside strings
- Use the
str.format()method for string formatting - Apply the format specification mini-language for alignment, padding, and precision
- Format numbers, dates, and other values for display
- Choose the right formatting approach for different situations
f-strings¶
Formatted string literals, or f-strings, were introduced in Python 3.6 and are the most modern and readable way to embed values inside strings. You create an f-string by placing an f or F before the opening quotation mark, and then placing expressions inside curly braces {}.
Basic f-string syntax¶
The simplest use of an f-string is to insert the value of a variable directly into a string.
name = "Ada Lovelace"
greeting = f"Hello, {name}!"
print(greeting)
Embedding expressions¶
f-strings are not limited to simple variables. You can place any valid Python expression inside the curly braces, including arithmetic operations and method calls.
# Arithmetic expressions inside f-strings
width = 12
height = 8
print(f"The area of the rectangle is {width * height} square metres.")
# Method calls inside f-strings
message = "string formatting is powerful"
print(f"Capitalised: {message.capitalize()}")
print(f"Uppercase: {message.upper()}")
print(f"Word count: {len(message.split())}")
Calling functions inside f-strings¶
You can call any function inside the curly braces, including built-in functions and your own custom functions.
import math
radius = 5
print(f"The circumference of a circle with radius {radius} is {2 * math.pi * radius:.2f} metres.")
Multi-line f-strings¶
You can create multi-line f-strings using triple quotes. This is useful when you need to format a block of text with embedded values.
product = "Python Handbook"
price = 29.99
quantity = 3
receipt = f"""
Order Summary
-------------
Product: {product}
Price: £{price:.2f}
Quantity: {quantity}
Total: £{price * quantity:.2f}
"""
print(receipt)
Escaping braces in f-strings¶
If you need to include a literal curly brace in an f-string, you double it. Use {{ to produce a single { and }} to produce a single }.
language = "Python"
print(f"In {language}, you define a dictionary like this: {{\"key\": \"value\"}}")
The str.format() method¶
Before f-strings were introduced, the str.format() method was the preferred way to format strings. It is still useful in situations where the format string is not known until runtime, or when you need to reuse a template.
Positional arguments¶
You can refer to arguments by their position (starting from zero), or omit the index entirely to use them in order.
# Implicit positional arguments
print("Hello, {}! You have {} new messages.".format("Ada", 5))
# Explicit positional arguments
print("Hello, {0}! You have {1} new messages.".format("Ada", 5))
Named arguments¶
Named arguments make format strings easier to read and maintain, especially when there are many placeholders.
template = "Dear {name}, your order #{order_id} has been dispatched."
print(template.format(name="Ada", order_id=1042))
Format specification mini-language¶
Both f-strings and str.format() support a powerful mini-language for controlling how values are displayed. You place the format specification after a colon inside the curly braces, for example {value:spec}.
Alignment and width¶
You can control the alignment of text within a given width using the following alignment characters:
<-- left-aligned (the default for strings)>-- right-aligned (the default for numbers)^-- centred
word = "hello"
print(f"Left: '{word:<15}'")
print(f"Right: '{word:>15}'")
print(f"Centre: '{word:^15}'")
Fill characters¶
By default, padding uses spaces. You can specify a different fill character by placing it before the alignment character.
title = "Report"
print(f"{title:*^30}")
print(f"{title:-<30}")
print(f"{title:.>30}")
Precision for floating-point numbers¶
Use .nf to control the number of decimal places displayed for a floating-point number, where n is the number of decimal places.
pi = 3.141592653589793
print(f"Default: {pi}")
print(f"Two decimals: {pi:.2f}")
print(f"Four decimals: {pi:.4f}")
print(f"No decimals: {pi:.0f}")
Type codes¶
Type codes specify how a value should be presented. Here are some of the most commonly used type codes:
| Code | Description | Example |
|---|---|---|
d |
Integer (decimal) | 42 |
f |
Fixed-point notation | 3.14 |
e |
Scientific notation | 3.14e+00 |
% |
Percentage | 75.00% |
b |
Binary | 101010 |
x |
Hexadecimal (lowercase) | 2a |
o |
Octal | 52 |
number = 42
print(f"Decimal: {number:d}")
print(f"Binary: {number:b}")
print(f"Hexadecimal: {number:x}")
print(f"Octal: {number:o}")
fraction = 0.75
print(f"Fixed-point: {fraction:f}")
print(f"Scientific: {fraction:e}")
print(f"Percentage: {fraction:%}")
Thousands separator¶
For large numbers, you can add a comma or underscore as a thousands separator to improve readability.
population = 67886011
print(f"With comma: {population:,}")
print(f"With underscore: {population:_}")
# You can combine the thousands separator with other format options
revenue = 1234567.89
print(f"Revenue: £{revenue:,.2f}")
Sign control¶
You can control how the sign of a number is displayed using the following options:
+-- show the sign for both positive and negative numbers--- show the sign only for negative numbers (the default)(space) -- use a leading space for positive numbers and a minus sign for negative numbers
positive = 42
negative = -42
print(f"Plus sign: {positive:+d} {negative:+d}")
print(f"Minus only: {positive:-d} {negative:-d}")
print(f"Space: {positive: d} {negative: d}")
Formatting numbers¶
Number formatting is one of the most common uses of the format specification mini-language. Let us look at some practical examples.
Floating-point precision¶
When working with floating-point numbers, controlling decimal places is essential for clean output.
temperature = 21.67834
print(f"Raw value: {temperature}")
print(f"One decimal: {temperature:.1f} degrees")
print(f"Two decimals: {temperature:.2f} degrees")
print(f"Scientific: {temperature:.2e}")
Percentages¶
The % type code multiplies the value by 100 and appends a percent sign.
completion = 0.874
accuracy = 0.9523
print(f"Completion: {completion:.1%}")
print(f"Accuracy: {accuracy:.2%}")
Currency-style formatting¶
Combining the thousands separator, decimal precision, and a currency symbol produces clean financial output.
salary = 52750.00
bonus = 3200.50
deduction = -1500.00
print(f"Salary: £{salary:>12,.2f}")
print(f"Bonus: £{bonus:>12,.2f}")
print(f"Deduction: £{deduction:>12,.2f}")
print(f" {'':->13}")
print(f"Total: £{salary + bonus + deduction:>12,.2f}")
Practical examples¶
Now that you have learned the building blocks, let us put them together in some realistic scenarios.
Creating a formatted table¶
Formatting is especially useful when you need to display data in a neatly aligned table.
# Data for the table
students = [
("Ada Lovelace", 92.5, "A"),
("Charles Babbage", 87.3, "B"),
("Grace Hopper", 95.8, "A"),
("Alan Turing", 91.0, "A"),
]
# Print table header
print(f"{'Name':<20} {'Score':>8} {'Grade':>6}")
print(f"{'':-<20} {'':-<8} {'':-<6}")
# Print each row
for name, score, grade in students:
print(f"{name:<20} {score:>8.1f} {grade:>6}")
Exercises¶
Try the following exercises to practise what you have learned. Write your solution in each empty code cell, then compare with the solutions below.
Exercise 1: Personal greeting¶
Create variables for a first name, a last name, and an age. Then use an f-string to print a message in the following format:
My name is Ada Lovelace and I am 36 years old.
# Exercise 1: Write your solution here
Exercise 2: Price list¶
Given the following list of items and prices, print a neatly formatted price list where item names are left-aligned in a 20-character column and prices are right-aligned with two decimal places and a pound sign.
items = [("Notebook", 4.99), ("Fountain Pen", 18.50), ("Ink Cartridges", 7.25)]
# Exercise 2: Write your solution here
items = [("Notebook", 4.99), ("Fountain Pen", 18.50), ("Ink Cartridges", 7.25)]
Exercise 3: Number base converter¶
Write a loop that prints the numbers 1 to 16 in decimal, binary, octal, and hexadecimal, each right-aligned in a column of width 6. Include column headers.
# Exercise 3: Write your solution here
Solutions¶
# Solution 1: Personal greeting
first_name = "Ada"
last_name = "Lovelace"
age = 36
print(f"My name is {first_name} {last_name} and I am {age} years old.")
# Solution 2: Price list
items = [("Notebook", 4.99), ("Fountain Pen", 18.50), ("Ink Cartridges", 7.25)]
for name, price in items:
print(f"{name:<20} £{price:>5.2f}")
# Solution 3: Number base converter
print(f"{'Dec':>6} {'Bin':>6} {'Oct':>6} {'Hex':>6}")
print(f"{'-' * 6} {'-' * 6} {'-' * 6} {'-' * 6}")
for i in range(1, 17):
print(f"{i:>6d} {i:>6b} {i:>6o} {i:>6x}")
Summary¶
In this tutorial, you have learned how to format strings in Python using two approaches:
- f-strings provide a concise, readable syntax for embedding expressions directly inside strings. They are the recommended approach for most formatting tasks.
str.format()is useful when you need to reuse a template or when the format string is determined at runtime.- The format specification mini-language gives you fine-grained control over alignment, padding, width, precision, type codes, thousands separators, and sign display.
Key points to remember:
- Use f-strings (
f"...") for most formatting tasks - Control alignment with
<,>, and^ - Specify decimal precision with
.nf - Use
,or_for thousands separators - Use type codes (
d,f,e,%,b,x,o) to control number presentation - Escape literal braces with
{{and}}
In the next tutorial, String searching, you will learn how to search for patterns within strings, find substrings, and test whether strings contain specific content.