Python String Formatting

Python string formatting is the process of inserting values into a string and controlling exactly how those values are displayed. Whether you are building a user-facing message, printing a report, or logging data, Python string formatting gives you the tools to place variables, numbers, and expressions directly inside your text with precise control over spacing, alignment, and number display. It is one of the most commonly used features in Python and something you will rely on in virtually every project.

There are three main approaches to Python string formatting in modern Python. The newest and most popular is f-strings, introduced in Python 3.6. Before that, the format() method was the standard, and even earlier, Python used the percent operator for string formatting. Each approach has its own syntax and quirks, but they all solve the same core problem of combining data with text in a clean, readable way.

F-Strings for Python String Formatting

F-strings are the most modern and widely recommended way to do Python string formatting. You create an f-string by placing the letter f right before the opening quote of a string. Inside the string, you use curly braces to embed any Python expression, and Python evaluates it and inserts the result directly into the string.

name = "Alice"
age = 30
message = f"My name is {name} and I am {age} years old."
print(message)
Output
My name is Alice and I am 30 years old.

The curly braces act as placeholders. Python evaluates whatever is inside them at runtime and converts the result to a string. You are not limited to simple variables either. You can put full expressions inside the braces, including arithmetic, function calls, and method calls.

price = 49.99
quantity = 3
print(f"Total cost: {price * quantity}")
Output
Total cost: 149.97

F-strings are faster than other Python string formatting methods because Python evaluates them at compile time rather than building the string through function calls. They are also easier to read because you see the variable names right where they appear in the text, rather than matching placeholders to arguments somewhere else in the line.

language = "python"
print(f"I am learning {language.upper()} programming.")
Output
I am learning PYTHON programming.

You can call any method or function inside the curly braces. This makes f-strings extremely flexible for Python string formatting because you can transform values right at the point of insertion without needing a separate variable.

Format Specifiers in F-Strings

Python string formatting becomes truly powerful when you use format specifiers. A format specifier goes inside the curly braces after a colon, and it tells Python exactly how to display the value. You can control decimal places, alignment, padding, and much more.

To control decimal places for floating-point numbers, you use the syntax :.Nf where N is the number of decimal places you want.

pi = 3.14159265
print(f"Pi rounded to 2 decimal places: {pi:.2f}")
print(f"Pi rounded to 4 decimal places: {pi:.4f}")
Output
Pi rounded to 2 decimal places: 3.14
Pi rounded to 4 decimal places: 3.1416

You can set a minimum width for a field by putting a number before the format type. This is useful for aligning columns of data in Python string formatting.

for item in ["Apples", "Bananas", "Cherries"]:
    print(f"{item:>15}")
Output
         Apples
        Bananas
       Cherries

The greater-than sign means right-align within the given width. You can also use the less-than sign for left alignment and the caret for center alignment.

header = "Product"
print(f"{header:<20} {'Price':>10}")
print(f"{'Laptop':<20} {'$999.99':>10}")
print(f"{'Mouse':<20} {'$29.99':>10}")
Output
Product                   Price
Laptop                  $999.99
Mouse                    $29.99

For large numbers, you can add a comma separator to make them easier to read. This is a handy Python string formatting trick for displaying financial data or statistics.

population = 7900000000
print(f"World population: {population:,}")
Output
World population: 7,900,000,000

You can also use an underscore as a thousands separator if you prefer that style.

distance = 384400
print(f"Distance to the Moon: {distance:_} km")
Output
Distance to the Moon: 384_400 km

Percentage and Scientific Notation Formatting

Python string formatting includes built-in support for displaying numbers as percentages and in scientific notation. These format types save you from doing manual multiplication or formatting.

The percent format type multiplies a number by 100 and appends a percent sign automatically.

success_rate = 0.856
print(f"Success rate: {success_rate:.1%}")
Output
Success rate: 85.6%

For very large or very small numbers, scientific notation keeps things readable. Use the e format specifier for this kind of Python string formatting.

avogadro = 6.02214076e23
print(f"Avogadro's number: {avogadro:.4e}")
Output
Avogadro's number: 6.0221e+23

You can also display integers in different number bases using Python string formatting. The b specifier gives binary, o gives octal, x gives hexadecimal in lowercase, and X gives hexadecimal in uppercase.

number = 255
print(f"Binary: {number:b}")
print(f"Octal: {number:o}")
print(f"Hex (lower): {number:x}")
print(f"Hex (upper): {number:X}")
Output
Binary: 11111111
Octal: 377
Hex (lower): ff
Hex (upper): FF

The format() Method for Python String Formatting

Before f-strings existed, the format() method was the primary way to do Python string formatting. You call format() on a string that contains curly brace placeholders, and pass the values as arguments. The method replaces each placeholder with the corresponding value.

name = "Bob"
score = 95
result = "Student {} scored {} points.".format(name, score)
print(result)
Output
Student Bob scored 95 points.

You can use numbered indices inside the braces to control which argument goes where. This is useful when you need to reuse the same value multiple times or change the order of insertion in your Python string formatting.

print("{0} is learning {1}. {0} loves {1}!".format("Carol", "Python"))
Output
Carol is learning Python. Carol loves Python!

You can also use named placeholders, which makes the code more readable when you have many values to insert.

message = "Hello, {name}! You have {count} new messages.".format(
    name="David",
    count=5
)
print(message)
Output
Hello, David! You have 5 new messages.

All the same format specifiers that work in f-strings also work with the format() method. You put them after a colon inside the curly braces, just like with f-strings.

price = 1234.5
print("Price: {:>12,.2f}".format(price))
Output
Price:     1,234.50

The format() method is still perfectly valid Python string formatting and you will see it in older codebases and in situations where you need to define a template string separately from the data that fills it.

template = "The {animal} jumped over the {obstacle}."
print(template.format(animal="fox", obstacle="fence"))
print(template.format(animal="cat", obstacle="wall"))
Output
The fox jumped over the fence.
The cat jumped over the wall.

The % Operator for Python String Formatting

The percent operator is the oldest method of Python string formatting, borrowed from C's printf syntax. You place percent-based placeholders inside a string and then use the percent operator to provide the values. While this approach is less common in new code, you will still encounter it in legacy projects and in logging statements.

The placeholder %s converts any value to a string, %d formats an integer, and %f formats a floating-point number.

name = "Eve"
age = 28
print("Name: %s, Age: %d" % (name, age))
Output
Name: Eve, Age: 28

You can control the width and precision of numbers just like with the other Python string formatting methods. Place a number between the percent sign and the format letter for width, and use a dot followed by a number for decimal precision.

value = 3.14159
print("Pi is approximately %.2f" % value)
Output
Pi is approximately 3.14

For padding and alignment with the percent operator, you specify a width number. A positive number right-aligns the value, and a negative number left-aligns it.

for fruit in ["Apple", "Banana", "Cherry"]:
    print("%-15s | In stock" % fruit)
Output
Apple           | In stock
Banana          | In stock
Cherry          | In stock

You can also use a dictionary with the percent operator for named Python string formatting. Place the key name in parentheses between the percent sign and the format letter.

data = {"city": "Paris", "temp": 22.5}
print("The temperature in %(city)s is %(temp).1f°C." % data)
Output
The temperature in Paris is 22.5°C.

Padding and Fill Characters

Python string formatting lets you choose any character as a fill character for padding. By default, Python uses spaces, but you can specify any single character before the alignment symbol.

title = "Menu"
print(f"{title:*^30}")
Output
*************Menu*************

The asterisk before the caret tells Python to use asterisks as the fill character, and the caret centers the text within 30 characters. You can use dashes, dots, or any other character as the fill.

print(f"{'Section 1':-<30}")
print(f"{'Section 2':.>30}")
print(f"{'Section 3':=^30}")
Output
Section 1---------------------
.....................Section 2
==========Section 3===========

This kind of Python string formatting is especially useful for creating text-based reports, menus, and formatted console output.

Zero-Padding Numbers

A common Python string formatting task is padding numbers with leading zeros. This is useful for formatting dates, file names, and ID numbers. You place a zero before the width specifier to pad with zeros.

for i in range(1, 6):
    print(f"File_{i:03d}.txt")
Output
File_001.txt
File_002.txt
File_003.txt
File_004.txt
File_005.txt

You can also add a sign indicator to always show the plus or minus sign on numbers. The plus specifier shows the sign for both positive and negative numbers.

values = [42, -17, 0, 100]
for v in values:
    print(f"{v:+d}")
Output
+42
-17
+0
+100

String Formatting with Dictionaries and Objects

Python string formatting works naturally with dictionaries and object attributes. With f-strings, you can access dictionary values and object properties directly inside the curly braces.

person = {"name": "Grace", "role": "Developer"}
print(f"{person['name']} works as a {person['role']}.")
Output
Grace works as a Developer.

For objects, you access attributes with dot notation inside the f-string, which makes Python string formatting with custom classes very straightforward.

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

item = Product("Keyboard", 75.50)
print(f"Product: {item.name}, Price: ${item.price:.2f}")
Output
Product: Keyboard, Price: $75.50

With the format() method, you can use numbered or named references and then access attributes or keys using dot notation or bracket notation inside the placeholder.

data = {"x": 10, "y": 20}
print("Coordinates: ({x}, {y})".format(**data))
Output
Coordinates: (10, 20)

The double asterisk unpacks the dictionary so that its keys become named arguments to format(). This is a clean pattern for Python string formatting when your data is already stored in a dictionary.

Multiline F-Strings

When you need to format longer text blocks, Python string formatting with f-strings works perfectly with triple-quoted strings. You can spread your formatted text across multiple lines while still embedding expressions.

name = "Hank"
items = 3
total = 59.97

receipt = f"""
Customer: {name}
Items purchased: {items}
Total amount: ${total:.2f}
Average per item: ${total / items:.2f}
"""
print(receipt)
Output

Customer: Hank
Items purchased: 3
Total amount: $59.97
Average per item: $19.99

This is much cleaner than concatenating strings or using multiple print statements. The expressions inside the braces are still evaluated normally, so you can do arithmetic and call functions right inside the multiline f-string.

Complete Working Example

This full working example demonstrates all three Python string formatting methods together. It builds a formatted product report with aligned columns, currency formatting, percentage calculations, and various display styles to show how each technique works in a realistic scenario.

products = [
    {"name": "Wireless Mouse", "price": 29.99, "stock": 150, "rating": 0.92},
    {"name": "Mechanical Keyboard", "price": 89.50, "stock": 75, "rating": 0.88},
    {"name": "USB-C Hub", "price": 45.00, "stock": 200, "rating": 0.95},
    {"name": "Monitor Stand", "price": 120.00, "stock": 30, "rating": 0.78},
]

print(f"{'PRODUCT INVENTORY REPORT':=^60}")
print()

header = f"{'Product':<25} {'Price':>10} {'Stock':>8} {'Rating':>10}"
print(header)
print(f"{'-' * 60}")

total_value = 0
for product in products:
    name = product["name"]
    price = product["price"]
    stock = product["stock"]
    rating = product["rating"]

    print(f"{name:<25} ${price:>9.2f} {stock:>8,} {rating:>9.1%}")
    total_value += price * stock

print(f"{'-' * 60}")

print(f"{'Total Inventory Value:':<25} ${total_value:>9,.2f}")
print()

print("=" * 60)
print("USING format() METHOD:")
print("=" * 60)
row_template = "{:<25} ${:>9.2f} {:>8,} {:>9.1%}"
for product in products:
    print(row_template.format(
        product["name"],
        product["price"],
        product["stock"],
        product["rating"]
    ))

print()
print("=" * 60)
print("USING % OPERATOR:")
print("=" * 60)
for product in products:
    print("%-25s $%9.2f %8d     %.0f%%" % (
        product["name"],
        product["price"],
        product["stock"],
        product["rating"] * 100
    ))

print()
summary = f"""
{'SUMMARY':*^60}
Total products: {len(products)}
Most expensive: {max(products, key=lambda p: p['price'])['name']}
Highest rated: {max(products, key=lambda p: p['rating'])['name']}
Total inventory value: ${total_value:,.2f}
{'':*^60}"""
print(summary)
Output
==================PRODUCT INVENTORY REPORT==================

Product                        Price    Stock     Rating
------------------------------------------------------------
Wireless Mouse              $   29.99      150     92.0%
Mechanical Keyboard         $   89.50       75     88.0%
USB-C Hub                   $   45.00      200     95.0%
Monitor Stand               $  120.00       30     78.0%
------------------------------------------------------------
Total Inventory Value:      $20,212.50

============================================================
USING format() METHOD:
============================================================
Wireless Mouse              $    29.99      150     92.0%
Mechanical Keyboard         $    89.50       75     88.0%
USB-C Hub                   $    45.00      200     95.0%
Monitor Stand               $   120.00       30     78.0%

============================================================
USING % OPERATOR:
============================================================
Wireless Mouse              $    29.99      150     92%
Mechanical Keyboard         $    89.50       75     88%
USB-C Hub                   $    45.00      200     95%
Monitor Stand               $   120.00       30     78%

****************************SUMMARY*****************************
Total products: 4
Most expensive: Monitor Stand
Highest rated: USB-C Hub
Total inventory value: $20,212.50
************************************************************