Python string formatting is one of the most essential skills you'll use every single day as a Python developer. Whether you're printing user messages, building dynamic reports, or logging debug info, python string formatting gives you precise control over how your data appears as text. In this guide, you'll learn all major python string formatting techniques — from the classic python % operator string style to the modern f-string approach — with clear examples and detailed explanations so you can choose the right method every time.
Raw string concatenation using + gets messy fast. Python string formatting solves this cleanly by letting you embed variables, control decimal places, align columns, and pad numbers — all inside a single readable string. Python offers four main approaches to string formatting, each with its own strengths.
The python % operator string style is the oldest formatting method in Python, borrowed from C's printf. You place % placeholders inside a string and supply values after a second %.
Short Example:
name = "Alice"
score = 95
print("Student: %s, Score: %d" % (name, score))
# Output: Student: Alice, Score: 95
Common % Format Specifiers:
| Specifier | Meaning |
|---|---|
%s | String |
%d | Integer |
%f | Float |
%e | Scientific notation |
%x | Hexadecimal |
Controlling float precision with % operator:
temperature = 36.6789
print("Body temperature: %.2f°C" % temperature)
# Output: Body temperature: 36.68°C
The .2 before f tells Python to show exactly two decimal places. This is one of the core python format specifiers available across all formatting styles.
Padding and alignment:
item = "Keyboard"
price = 45.5
print("%-15s $%8.2f" % (item, price))
# Output: Keyboard $ 45.50
%-15s left-aligns the string in a 15-character field. %8.2f right-aligns the float in an 8-character field with 2 decimal places. This is how you python align string output using the % operator.
The python format() method was introduced in Python 2.6 and is more readable and powerful than the % operator. You use {} placeholders inside strings and call .format() with the values.
Short Example:
city = "Berlin"
population = 3645000
print("City: {}, Population: {}".format(city, population))
# Output: City: Berlin, Population: 3645000
Using positional and keyword arguments:
print("{0} is {1} years old. {0} loves Python.".format("Riya", 24))
# Output: Riya is 24 years old. Riya loves Python.
print("{name} works at {company}.".format(name="Sam", company="TechCorp"))
# Output: Sam works at TechCorp.
Positional arguments ({0}, {1}) let you reuse the same value multiple times. Keyword arguments make code self-documenting and easier to maintain.
Number formatting with format():
big_number = 1502348.7623
print("Revenue: {:,.2f}".format(big_number))
# Output: Revenue: 1,502,348.76
The :,.2f format spec inside {} adds a comma separator and rounds to 2 decimal places. This is the python number formatting string approach most developers use for financial or statistical data.
Alignment using format() — python align string output:
headers = ["Product", "Qty", "Price"]
print("{:<15} {:>5} {:>10}".format(*headers))
print("{:<15} {:>5} {:>10.2f}".format("USB Cable", 12, 8.99))
print("{:<15} {:>5} {:>10.2f}".format("Monitor Stand", 3, 34.5))
Product Qty Price
USB Cable 12 8.99
Monitor Stand 3 34.50
< means left-align, > means right-align, and the number controls the column width. This is the standard way to python align string output when building simple tables or reports.
F-strings are the most modern and recommended python string formatting approach, available from Python 3.6+. You prefix the string with f and embed expressions directly inside {}.
Short Example:
product = "Laptop"
discount = 0.15
print(f"{product} is on sale with {discount:.0%} off!")
# Output: Laptop is on sale with 15% off!
F-strings support any valid Python expression inside the braces — not just variable names.
Inline expressions:
a = 7
b = 3
print(f"{a} divided by {b} equals {a / b:.4f}")
# Output: 7 divided by 3 equals 2.3333
Python format specifiers inside f-strings:
pi = 3.14159265
print(f"Pi rounded to 3 decimals: {pi:.3f}")
print(f"Pi in scientific notation: {pi:.2e}")
print(f"Pi as percentage: {pi:.1%}")
Pi rounded to 3 decimals: 3.142
Pi in scientific notation: 3.14e+00
Pi as percentage: 314.2%
These are python format specifiers in action — the part after : inside {} controls width, precision, type, and alignment.
Padding and alignment with f-strings:
students = [("Arjun", 88), ("Priya", 95), ("Leo", 72)]
print(f"{'Name':<10} {'Score':>6}")
print("-" * 17)
for name, score in students:
print(f"{name:<10} {score:>6}")
Name Score
-----------------
Arjun 88
Priya 95
Leo 72
Debugging with f-strings (Python 3.8+):
value = 42
print(f"{value=}")
# Output: value=42
The = specifier prints both the variable name and its value — extremely useful for quick debugging.
The string.Template class from Python's standard library offers a simpler substitution syntax using $. It's designed for cases where end users might supply the format string, since it's safer against injection attacks.
Short Example:
from string import Template
greeting = Template("Hello, $username! You have $messages new messages.")
result = greeting.substitute(username="Neha", messages=5)
print(result)
# Output: Hello, Neha! You have 5 new messages.
Using safe_substitute():
from string import Template
template = Template("Order #$order_id placed by $customer")
print(template.safe_substitute(order_id=1042))
# Output: Order #1042 placed by $customer
safe_substitute() leaves missing placeholders as-is instead of raising a KeyError. This is useful when you're partially filling in a template and want to avoid crashes.
Python string templates are not as feature-rich as f-strings or the python format() method, but they shine in config files, email templates, or any scenario where non-developers write the template text.
Python format specifiers follow this general pattern:
{[field_name]:[fill][align][sign][width][grouping][.precision][type]}
| Component | Options | Example |
|---|---|---|
| align | < left, > right, ^ center | {:<10} |
| sign | + always, - only negative | {:+.2f} |
| width | integer | {:8} |
| grouping | , or _ | {:,} |
| precision | .n | {:.3f} |
| type | d, f, e, s, x, % | {:x} |
Centering text:
title = "Report"
print(f"{title:^20}")
# Output: Report
Number with sign:
change = -250.5
print(f"Balance change: {change:+,.2f}")
# Output: Balance change: -250.50
This example brings together all the python string formatting techniques in a practical inventory report generator.
from string import Template
# --- Sample inventory data ---
inventory = [
{"name": "Wireless Mouse", "sku": "A1042", "qty": 150, "price": 29.99},
{"name": "Mechanical Keyboard", "sku": "B2081", "qty": 47, "price": 89.5},
{"name": "USB-C Hub", "sku": "C3310", "qty": 320, "price": 14.75},
{"name": "Monitor Stand", "sku": "D4002", "qty": 18, "price": 45.0},
]
# --- % operator: format SKU label ---
def format_sku_label(sku, name):
return "SKU: %-8s | Item: %s" % (sku, name)
# --- str.format(): column headers ---
header = "{:<22} {:>6} {:>10} {:>12}".format("Product", "SKU", "Qty", "Unit Price")
divider = "-" * 54
# --- f-strings: row data with number formatting ---
def format_row(item):
name = item["name"]
sku = item["sku"]
qty = item["qty"]
price = item["price"]
total = qty * price
return f"{name:<22} {sku:>6} {qty:>10,} {price:>12,.2f}"
# --- Template: summary message ---
summary_template = Template(
"\nInventory summary for $warehouse warehouse — $total_items SKUs tracked."
)
# --- Output ---
print("=" * 54)
print(" WAREHOUSE INVENTORY REPORT")
print("=" * 54)
print(header)
print(divider)
grand_total = 0
for item in inventory:
print(format_row(item))
grand_total += item["qty"] * item["price"]
print(divider)
print(f"{'TOTAL VALUE':>40} {grand_total:>12,.2f}")
print()
for item in inventory:
print(format_sku_label(item["sku"], item["name"]))
print(summary_template.substitute(warehouse="Central", total_items=len(inventory)))
Expected Output:
======================================================
WAREHOUSE INVENTORY REPORT
======================================================
Product SKU Qty Unit Price
------------------------------------------------------
Wireless Mouse A1042 150 29.99
Mechanical Keyboard B2081 47 89.50
USB-C Hub C3310 320 14.75
Monitor Stand D4002 18 45.00
------------------------------------------------------
TOTAL VALUE 14,462.50
SKU: A1042 | Item: Wireless Mouse
SKU: B2081 | Item: Mechanical Keyboard
SKU: C3310 | Item: USB-C Hub
SKU: D4002 | Item: Monitor Stand
Inventory summary for Central warehouse — 4 SKUs tracked.
This example uses all four python string formatting styles together. The python % operator string handles SKU label padding, the python format() method builds aligned column headers, f-strings format each data row with the python number formatting string pattern including commas and 2 decimal places, and string.Template produces the human-readable summary. Each approach showcases a different set of python format specifiers and python align string output techniques.
For more details, visit the official Python string formatting documentation and the f-string reference.
Ready to go deeper? This guide is part of a complete Python tutorial series covering everything from basics to advanced topics. Whether you're just starting out or looking to sharpen your skills, the full series has you covered. Learn the full Python tutorial here.