Python String Formatting
Learn different methods to format strings in Python including f-strings, format(), and % formatting.
String Formatting
To make sure a string will display as expected, we can format the result with the format() method.
String format()
The format() method allows you to format selected parts of a string.
Sometimes there are parts of a text that you do not control, maybe they come from a database, or user input?
To control such values, add placeholders (curly brackets {}) in the text, and run the values through the format() method:
Example - Add a placeholder where you want to display the price:
price = 49
txt = "The price is {} dollars"
print(txt.format(price)) You can add parameters inside the curly brackets to specify how to convert the value:
Example - Format the price to be displayed as a number with two decimals:
price = 49
txt = "The price is {:.2f} dollars"
print(txt.format(price)) Multiple Values
If you want to use more values, just add more values to the format() method:
Example
quantity = 3
itemno = 567
price = 49
myorder = "I want {} pieces of item number {} for {:.2f} dollars."
print(myorder.format(quantity, itemno, price)) Index Numbers
You can use index numbers (a number inside the curly brackets {0}) to be sure the values are placed in the correct placeholders:
Example
quantity = 3
itemno = 567
price = 49
myorder = "I want {0} pieces of item number {1} for {2:.2f} dollars."
print(myorder.format(quantity, itemno, price)) Also, if you want to refer to the same value more than once, use the index number:
Example
age = 36
name = "John"
txt = "His name is {1}. {1} is {0} years old."
print(txt.format(age, name)) Named Indexes
You can also use named indexes by entering a name inside the curly brackets {carname}, but then you must use names when you pass the parameter values txt.format(carname = "Ford"):
Example
myorder = "I have a {carname}, it is a {model}."
print(myorder.format(carname = "Ford", model = "Mustang")) F-Strings (Formatted String Literals)
F-strings were introduced in Python 3.6 and provide a more readable and concise way to format strings:
Example - Basic f-string usage:
name = "John"
age = 36
txt = f"My name is {name} and I am {age} years old"
print(txt) Example - F-strings with expressions:
price = 59
tax_rate = 0.08
total = price * (1 + tax_rate)
txt = f"Price: ${price}, Tax: {tax_rate:.1%}, Total: ${total:.2f}"
print(txt) Example - F-strings with function calls:
import datetime
name = "Alice"
now = datetime.datetime.now()
txt = f"Hello {name.upper()}, today is {now.strftime('%Y-%m-%d')}"
print(txt) Format Specifiers
Format specifiers allow you to control how values are displayed:
Advanced Formatting Examples
Number Formatting
number = 1234567.89
# Different number formats
print(f"Default: {number}")
print(f"Two decimals: {number:.2f}")
print(f"Thousands separator: {number:,.2f}")
print(f"Scientific notation: {number:.2e}")
print(f"Percentage: {0.1234:.2%}")
print(f"Padded: {42:08d}")
print(f"Hexadecimal: {255:x}")
print(f"Binary: {10:b}")
# Currency formatting
price = 1234.56
print(f"Price: ${price:,.2f}")
print(f"Price (padded): ${price:>10,.2f}") String Alignment and Padding
text = "Python"
# Alignment examples
print(f"Left aligned: '{text:<15}'")
print(f"Right aligned: '{text:>15}'")
print(f"Center aligned: '{text:^15}'")
print(f"Padded with dots: '{text:.<15}'")
print(f"Padded with stars: '{text:*^15}'")
# Creating a simple table
items = [("Apple", 1.20), ("Banana", 0.50), ("Orange", 0.80)]
print("\nFruit Price List:")
print("-" * 20)
for item, price in items:
print(f"{item:<10} ${price:>6.2f}") Date and Time Formatting
import datetime
now = datetime.datetime.now()
birthday = datetime.date(1990, 5, 15)
# Date formatting with f-strings
print(f"Current time: {now}")
print(f"Formatted date: {now:%Y-%m-%d}")
print(f"Formatted time: {now:%H:%M:%S}")
print(f"Full format: {now:%A, %B %d, %Y at %I:%M %p}")
print(f"Birthday: {birthday:%B %d, %Y}")
# Age calculation
age = (datetime.date.today() - birthday).days // 365
print(f"Age: {age} years old") Old-Style % Formatting
Python also supports the older % formatting method (similar to C's printf):
Example - % formatting:
name = "John"
age = 36
height = 5.9
# Basic % formatting
print("My name is %s" % name)
print("I am %d years old" % age)
print("My height is %.1f feet" % height)
# Multiple values
print("My name is %s and I am %d years old" % (name, age))
# Named placeholders
print("%(name)s is %(age)d years old" % {"name": name, "age": age}) Practical Examples
Report Generation
def generate_sales_report(sales_data):
"""Generate a formatted sales report"""
print("=" * 50)
print(f"{'SALES REPORT':^50}")
print("=" * 50)
total_sales = 0
total_quantity = 0
# Header
print(f"{'Product':<20} {'Qty':>8} {'Price':>10} {'Total':>10}")
print("-" * 50)
# Data rows
for product, quantity, price in sales_data:
total = quantity * price
total_sales += total
total_quantity += quantity
print(f"{product:<20} {quantity:>8d} ${price:>9.2f} ${total:>9.2f}")
# Summary
print("-" * 50)
print(f"{'TOTALS':<20} {total_quantity:>8d} {'':<10} ${total_sales:>9.2f}")
print("=" * 50)
# Statistics
avg_price = total_sales / total_quantity if total_quantity > 0 else 0
print(f"Average price per item: ${avg_price:.2f}")
print(f"Total items sold: {total_quantity:,}")
print(f"Total revenue: ${total_sales:,.2f}")
# Sample data
sales = [
("Laptop", 5, 999.99),
("Mouse", 25, 29.99),
("Keyboard", 15, 79.99),
("Monitor", 8, 299.99),
("Headphones", 12, 149.99)
]
generate_sales_report(sales) Configuration File Generator
def generate_config_file(config_data):
"""Generate a formatted configuration file"""
config_template = """
# Application Configuration File
# Generated on {timestamp}
[Database]
host = {db_host}
port = {db_port}
database = {db_name}
username = {db_user}
password = {db_pass}
[Server]
host = {server_host}
port = {server_port}
debug = {debug_mode}
workers = {worker_count}
[Logging]
level = {log_level}
file = {log_file}
max_size = {log_max_size}MB
backup_count = {log_backup_count}
[Features]
cache_enabled = {cache_enabled}
rate_limiting = {rate_limiting}
api_version = v{api_version}
"""
import datetime
# Add timestamp
config_data['timestamp'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# Format the configuration
formatted_config = config_template.format(**config_data)
return formatted_config.strip()
# Configuration data
config = {
'db_host': 'localhost',
'db_port': 5432,
'db_name': 'myapp',
'db_user': 'admin',
'db_pass': '********',
'server_host': '0.0.0.0',
'server_port': 8000,
'debug_mode': False,
'worker_count': 4,
'log_level': 'INFO',
'log_file': '/var/log/myapp.log',
'log_max_size': 100,
'log_backup_count': 5,
'cache_enabled': True,
'rate_limiting': True,
'api_version': '2.1'
}
print(generate_config_file(config)) Progress Bar with Formatting
import time
import sys
def show_progress(current, total, bar_length=40, prefix="Progress"):
"""Display a formatted progress bar"""
# Calculate percentage
percent = (current / total) * 100
# Calculate filled length
filled_length = int(bar_length * current // total)
# Create the bar
bar = '█' * filled_length + '-' * (bar_length - filled_length)
# Format the progress line
progress_line = f"\r{prefix}: |{bar}| {percent:.1f}% ({current}/{total})"
# Print without newline
sys.stdout.write(progress_line)
sys.stdout.flush()
# Print newline when complete
if current == total:
print()
def simulate_task():
"""Simulate a task with progress updates"""
total_steps = 100
print("Starting task simulation...")
for i in range(total_steps + 1):
show_progress(i, total_steps, prefix="Processing")
time.sleep(0.05) # Simulate work
print("Task completed!")
# Uncomment to run the simulation
# simulate_task()
# Static example of different progress states
print("Progress bar examples:")
show_progress(0, 100, prefix="Starting")
show_progress(25, 100, prefix="Quarter")
show_progress(50, 100, prefix="Half")
show_progress(75, 100, prefix="Three-quarters")
show_progress(100, 100, prefix="Complete") Data Table Formatter
def format_table(data, headers, title=None):
"""Format data as a nice table"""
if not data or not headers:
return "No data to display"
# Calculate column widths
col_widths = []
for i, header in enumerate(headers):
max_width = len(str(header))
for row in data:
if i < len(row):
max_width = max(max_width, len(str(row[i])))
col_widths.append(max_width + 2) # Add padding
# Create format string
row_format = "|".join(f"{{:<{width}}}" for width in col_widths)
separator = "+" + "+".join("-" * width for width in col_widths) + "+"
# Build the table
table_lines = []
# Title
if title:
total_width = sum(col_widths) + len(col_widths) - 1
table_lines.append("=" * total_width)
table_lines.append(f"{title:^{total_width}}")
table_lines.append("=" * total_width)
# Headers
table_lines.append(separator)
table_lines.append("|" + row_format.format(*headers) + "|")
table_lines.append(separator)
# Data rows
for row in data:
# Pad row if necessary
padded_row = list(row) + [""] * (len(headers) - len(row))
table_lines.append("|" + row_format.format(*padded_row) + "|")
table_lines.append(separator)
return "\n".join(table_lines)
# Example usage
employee_data = [
["John Doe", "Developer", 75000, "2020-01-15"],
["Jane Smith", "Designer", 65000, "2019-03-22"],
["Bob Johnson", "Manager", 85000, "2018-07-10"],
["Alice Brown", "Analyst", 60000, "2021-05-03"]
]
headers = ["Name", "Position", "Salary", "Start Date"]
print(format_table(employee_data, headers, "Employee Information"))
# Financial data example
financial_data = [
["Q1 2023", 125000, 98000, 27000],
["Q2 2023", 142000, 105000, 37000],
["Q3 2023", 138000, 102000, 36000],
["Q4 2023", 156000, 115000, 41000]
]
financial_headers = ["Quarter", "Revenue", "Expenses", "Profit"]
print("\n" + format_table(financial_data, financial_headers, "Quarterly Financial Report")) Best Practices
- Use f-strings for modern Python (3.6+) - They're more readable and performant
- Use .format() for older Python versions or when you need more complex formatting
- Avoid % formatting in new code unless maintaining legacy systems
- Be consistent - Choose one formatting method and stick with it in your project
- Use meaningful variable names in format strings for clarity
- Consider locale-specific formatting for international applications
- Use format specifiers to control number precision and alignment