✨ Text Formatting
Text formatting in Python allows you to create professional, readable output by controlling how data appears in strings. Using f-strings, format methods, and formatting specifications, you can align text, format numbers, and create polished user interfaces.
Think of text formatting as the typography of your programs - it transforms raw data into visually appealing, organized information that users can easily read and understand.
# F-string formatting basics
name = "Alice"
age = 30
city = "New York"
price = 19.99
tax_rate = 0.08575
# Simple variable insertion and expressions
greeting = f"Hello, {name}! You are {age} years old."
print(greeting)
print(f"Next year, {name} will be {age + 1} years old.")
print(f"{name} lives in {city} and is {age} years old.")
# Number formatting
total = price * (1 + tax_rate)
print(f"Price: ${price:.2f}")
print(f"Tax rate: {tax_rate:.1%}")
print(f"Total: ${total:.2f}")
# Integer formatting with separators
population = 8419000
print(f"NYC Population: {population:,}")
print(f"Scientific notation: {population:.2e}")
# Text alignment
items = [
("Laptop", 999.99),
("Mouse", 29.99),
("Keyboard", 79.99),
("Monitor", 249.99)
]
print("\nProduct Report")
print("-" * 25)
for product, price in items:
print(f"{product:<12} ${price:>8.2f}")
print("-" * 25)
total = sum(price for _, price in items)
print(f"{'Total':<12} ${total:>8.2f}")
🎯 Understanding String Formatting
Python provides multiple formatting approaches, each with specific advantages for different use cases and coding styles.
Advanced F-String Techniques
F-strings offer powerful features for complex formatting scenarios and dynamic string construction.
import datetime
# Variable insertion and expressions
user = "Alice"
score = 95
max_score = 100
grade_letter = "A"
# Expression evaluation and function calls
percentage = f"Score: {score/max_score:.1%}"
print(percentage)
now = datetime.datetime.now()
timestamp = f"Generated on {now.strftime('%Y-%m-%d at %H:%M:%S')}"
print(timestamp)
# Conditional expressions
status = f"Status: {'PASS' if score >= 70 else 'FAIL'}"
print(status)
# Complex object formatting
class Student:
def __init__(self, name, grades):
self.name = name
self.grades = grades
def average(self):
return sum(self.grades) / len(self.grades)
students = [
Student("Alice", [95, 87, 92, 88]),
Student("Bob", [78, 85, 82, 90]),
Student("Carol", [91, 94, 89, 96])
]
print("\nStudent Grade Report")
print("=" * 40)
print(f"{'Name':<10} {'Grades':<15} {'Average':<8} {'Status'}")
print("-" * 40)
for student in students:
avg = student.average()
grades_str = ", ".join(f"{g:2d}" for g in student.grades)
status = "PASS" if avg >= 80 else "FAIL"
print(f"{student.name:<10} {grades_str:<15} {avg:6.1f} {status}")
# Dictionary formatting
data = {"revenue": 1250000, "expenses": 890000, "employees": 45}
print(f"\nCompany Summary:")
print(f"Revenue: ${data['revenue']:,}")
print(f"Profit: ${data['revenue'] - data['expenses']:,}")
print(f"Profit per employee: ${(data['revenue'] - data['expenses']) / data['employees']:,.2f}")
⚡ Professional Formatting Patterns
Report Generation and Templates
Multi-line f-strings enable complex template creation for reports and structured output formatting.
def generate_invoice(customer, items, tax_rate=0.08):
"""Generate formatted invoice using multi-line f-strings"""
subtotal = sum(item['price'] * item['quantity'] for item in items)
tax_amount = subtotal * tax_rate
total = subtotal + tax_amount
# Multi-line f-string invoice
invoice = f"""
╔══════════════════════════════════════════════════════╗
║ INVOICE ║
╠══════════════════════════════════════════════════════╣
║ Customer: {customer['name']:<36} ║
║ Address: {customer['address']:<36} ║
║ Date: {datetime.datetime.now().strftime('%Y-%m-%d'):<36} ║
╠══════════════════════════════════════════════════════╣
║ Item Qty Price Total ║
╠══════════════════════════════════════════════════════╣"""
# Add items to invoice
for item in items:
item_total = item['price'] * item['quantity']
invoice += f"""
║ {item['name']:<22} {item['quantity']:>3} ${item['price']:>7.2f} ${item_total:>9.2f} ║"""
# Add totals
invoice += f"""
╠══════════════════════════════════════════════════════╣
║ Subtotal: ${subtotal:>9.2f} ║
║ Tax ({tax_rate:.1%}): ${tax_amount:>9.2f} ║
║ Total: ${total:>9.2f} ║
╚══════════════════════════════════════════════════════╝"""
return invoice
# Example usage
customer_info = {
"name": "Alice Johnson",
"address": "123 Main St, New York, NY 10001"
}
order_items = [
{"name": "Laptop Computer", "quantity": 1, "price": 999.99},
{"name": "Wireless Mouse", "quantity": 2, "price": 29.99},
{"name": "USB Cable", "quantity": 3, "price": 12.99}
]
invoice = generate_invoice(customer_info, order_items)
print(invoice)
Data Presentation and Tables
Formatting techniques create organized, professional data displays for reports and user interfaces.
def create_data_table(title, headers, data, number_columns=None):
"""Create formatted data table with proper alignment"""
if number_columns is None:
number_columns = []
# Calculate column widths
col_widths = []
for i, header in enumerate(headers):
max_width = len(header)
for row in data:
if i < len(row):
cell_width = len(str(row[i]))
max_width = max(max_width, cell_width)
col_widths.append(max_width + 2) # Add padding
# Create table
table = f"\n{title}\n"
table += "=" * len(title) + "\n"
# Header row
header_row = ""
for i, (header, width) in enumerate(zip(headers, col_widths)):
if i in number_columns:
header_row += f"{header:>{width}}"
else:
header_row += f"{header:<{width}}"
table += header_row + "\n"
table += "-" * len(header_row) + "\n"
# Data rows
for row in data:
data_row = ""
for i, (cell, width) in enumerate(zip(row, col_widths)):
if i in number_columns:
if isinstance(cell, float):
data_row += f"{cell:>{width}.2f}"
else:
data_row += f"{cell:>{width}}"
else:
data_row += f"{str(cell):<{width}}"
table += data_row + "\n"
return table
# Sales data example
sales_headers = ["Product", "Units Sold", "Unit Price", "Revenue"]
sales_data = [
["Laptop", 45, 999.99, 44999.55],
["Mouse", 120, 29.99, 3598.80],
["Keyboard", 85, 79.99, 6799.15],
["Monitor", 32, 299.99, 9599.68]
]
sales_table = create_data_table(
"Monthly Sales Report",
sales_headers,
sales_data,
number_columns=[1, 2, 3] # Align numbers to the right
)
print(sales_table)
# Performance metrics example
metrics_headers = ["Metric", "Current", "Target", "Status"]
metrics_data = [
["Response Time", "1.2s", "< 2.0s", "✅ Good"],
["Uptime", "99.8%", "> 99.5%", "✅ Good"],
["Memory Usage", "78%", "< 80%", "✅ Good"],
["CPU Usage", "85%", "< 75%", "⚠️ High"]
]
metrics_table = create_data_table(
"System Performance Metrics",
metrics_headers,
metrics_data
)
print(metrics_table)
🚀 Advanced Formatting Techniques
Format String Validation and Safety
Safe formatting practices prevent errors and ensure consistent output quality.
def safe_format_number(value, format_spec=".2f", default="N/A"):
"""Safely format numbers with error handling"""
try:
if value is None:
return default
# Convert to float if needed
if isinstance(value, str):
value = float(value)
return f"{value:{format_spec}}"
except (ValueError, TypeError):
return default
def safe_format_percentage(value, precision=1, default="N/A"):
"""Safely format percentages"""
try:
if value is None:
return default
value = float(value)
if not 0 <= value <= 1:
value = value / 100 # Convert from percentage to decimal
return f"{value:.{precision}%}"
except (ValueError, TypeError):
return default
# Test safe formatting
test_values = [
("123.456", ".2f"),
("invalid", ".2f"),
(None, ".2f"),
("75.5", "%"),
("not_a_number", "%")
]
print("Safe Number Formatting:")
for value, fmt in test_values:
if fmt == "%":
result = safe_format_percentage(value)
else:
result = safe_format_number(value, fmt)
print(f"Input: {value:>12} Format: {fmt:>4} Result: {result}")
# Template-based formatting with validation
class ReportTemplate:
"""Template class for consistent report formatting"""
def __init__(self, title_width=50):
self.title_width = title_width
def format_title(self, title):
"""Format report title with decorative borders"""
title = title.upper()
padding = (self.title_width - len(title)) // 2
return f"""
{'=' * self.title_width}
{' ' * padding}{title}{' ' * padding}
{'=' * self.title_width}"""
def format_section(self, section_name, content):
"""Format report section with consistent styling"""
return f"""
{section_name}:
{'-' * len(section_name)}
{content}
"""
def format_key_value(self, key, value, key_width=20):
"""Format key-value pairs with consistent alignment"""
return f"{key:<{key_width}}: {value}"
# Example usage
template = ReportTemplate()
print(template.format_title("Monthly Performance Report"))
print(template.format_section("Financial Summary",
template.format_key_value("Revenue", "$125,000.00") + "\n" +
template.format_key_value("Expenses", "$98,500.00") + "\n" +
template.format_key_value("Net Profit", "$26,500.00")
))
🌟 Real-World Applications
Configuration and Log Formatting
Structured formatting improves readability and maintainability of configuration files and logs.
import datetime
class LogFormatter:
"""Professional log formatting for applications"""
def __init__(self, include_timestamp=True, include_level=True):
self.include_timestamp = include_timestamp
self.include_level = include_level
def format_log_entry(self, level, message, module=None, details=None):
"""Format log entry with consistent structure"""
parts = []
if self.include_timestamp:
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
parts.append(f"[{timestamp}]")
if self.include_level:
parts.append(f"[{level.upper():>7}]")
if module:
parts.append(f"[{module}]")
parts.append(message)
log_line = " ".join(parts)
if details:
log_line += f"\n Details: {details}"
return log_line
def format_error(self, error_msg, error_code=None, stack_trace=None):
"""Format error messages with additional context"""
parts = ["ERROR:", error_msg]
if error_code:
parts.append(f"(Code: {error_code})")
error_line = " ".join(parts)
if stack_trace:
error_line += f"\n Stack Trace:\n{stack_trace}"
return self.format_log_entry("ERROR", error_line)
# Usage examples
logger = LogFormatter()
print("Application Log Entries:")
print(logger.format_log_entry("INFO", "Application started successfully", "main"))
print(logger.format_log_entry("DEBUG", "Database connection established", "db", "host=localhost:5432"))
print(logger.format_log_entry("WARNING", "High memory usage detected", "monitor", "usage=87%"))
print(logger.format_error("Database connection failed", "DB001", "ConnectionError: timeout after 30s"))
# Configuration file generation
def generate_config_file(settings):
"""Generate formatted configuration file"""
config_content = f"""# Application Configuration
# Generated on {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
for section, options in settings.items():
config_content += f"[{section.upper()}]\n"
for key, value in options.items():
# Format different value types appropriately
if isinstance(value, bool):
formatted_value = str(value).lower()
elif isinstance(value, str):
formatted_value = f'"{value}"'
else:
formatted_value = str(value)
config_content += f"{key} = {formatted_value}\n"
config_content += "\n"
return config_content
# Configuration example
app_settings = {
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp",
"ssl_enabled": True
},
"security": {
"max_login_attempts": 3,
"session_timeout": 1800,
"encryption_enabled": True
},
"logging": {
"level": "INFO",
"file_path": "/var/log/myapp.log",
"max_file_size": "10MB"
}
}
config_file = generate_config_file(app_settings)
print("Generated Configuration File:")
print(config_file)
Hands-on Exercise
Create a simple grade report formatter that displays student information in a neat, aligned table format. Use f-strings to format names, grades, and calculate averages with proper alignment and decimal places.
def format_grade_report(students):
# TODO: Create header with proper alignment
# TODO: Format each student's data in aligned columns
# TODO: Calculate and display class average
# TODO: Use f-strings for formatting
pass
def format_student_row(name, math_grade, english_grade, science_grade):
# TODO: Calculate student average
# TODO: Format row with proper alignment
# TODO: Return formatted string
pass
# TODO: Test your formatting
students = [
{"name": "Alice Johnson", "math": 95, "english": 87, "science": 92},
{"name": "Bob Smith", "math": 78, "english": 82, "science": 85},
{"name": "Carol Davis", "math": 88, "english": 91, "science": 89},
{"name": "David Wilson", "math": 92, "english": 85, "science": 88}
]
print("Student Grade Report")
print("=" * 60)
format_grade_report(students)
Solution and Explanation 💡
Click to see the complete solution
def format_grade_report(students):
# Create header with proper alignment
print(f"{'Name':<15} {'Math':>6} {'English':>8} {'Science':>8} {'Average':>8}")
print("-" * 55)
total_students = len(students)
class_total = 0
# Format each student's data in aligned columns
for student in students:
row = format_student_row(
student["name"],
student["math"],
student["english"],
student["science"]
)
print(row)
# Add to class total for average calculation
student_avg = (student["math"] + student["english"] + student["science"]) / 3
class_total += student_avg
# Calculate and display class average
if total_students > 0:
class_average = class_total / total_students
print("-" * 55)
print(f"{'Class Average:':<15} {'':<6} {'':<8} {'':<8} {class_average:>8.2f}")
def format_student_row(name, math_grade, english_grade, science_grade):
# Calculate student average
average = (math_grade + english_grade + science_grade) / 3
# Format row with proper alignment
# Name left-aligned, grades right-aligned with 2 decimal places for average
formatted_row = f"{name:<15} {math_grade:>6} {english_grade:>8} {science_grade:>8} {average:>8.2f}"
# Return formatted string
return formatted_row
# Test your formatting
students = [
{"name": "Alice Johnson", "math": 95, "english": 87, "science": 92},
{"name": "Bob Smith", "math": 78, "english": 82, "science": 85},
{"name": "Carol Davis", "math": 88, "english": 91, "science": 89},
{"name": "David Wilson", "math": 92, "english": 85, "science": 88}
]
print("Student Grade Report")
print("=" * 60)
format_grade_report(students)
# Additional formatting examples
print("\n" + "=" * 60)
print("Formatting Examples:")
print("=" * 60)
# Number formatting examples
price = 1234.567
percentage = 0.856
large_number = 1234567
print(f"Price with 2 decimals: ${price:.2f}")
print(f"Percentage: {percentage:.1%}")
print(f"Large number with commas: {large_number:,}")
# Alignment examples
items = [("Apples", 5), ("Bananas", 12), ("Cherries", 8)]
print(f"\n{'Item':<10} {'Quantity':>8}")
print("-" * 20)
for item, qty in items:
print(f"{item:<10} {qty:>8}")
Key Learning Points:
- 📌 f-string alignment: Use
<
for left,>
for right,^
for center alignment - 📌 Width specification:
{value:10}
sets minimum width of 10 characters - 📌 Decimal formatting:
{value:.2f}
shows 2 decimal places - 📌 Percentage formatting:
{value:.1%}
converts decimal to percentage - 📌 Number separators:
{value:,}
adds commas to large numbers
Essential Text Formatting Methods and Patterns
Understanding core formatting techniques enables professional output creation and data presentation.
Format Type | Purpose | Example | Result |
---|---|---|---|
f"{var}" | F-string variable insertion | f"Hello {name}" | "Hello Alice" |
f"{value:.2f}" | Decimal places | f"{3.14159:.2f}" | "3.14" |
f"{value:,}" | Thousands separator | f"{1234567:,}" | "1,234,567" |
f"{value:.1%}" | Percentage | f"{0.123:.1%}" | "12.3%" |
f"{text:<10}" | Left align | f"{'hello':<10}" | "hello " |
f"{text:>10}" | Right align | f"{'hello':>10}" | " hello" |
f"{text:^10}" | Center align | f"{'hello':^10}" | " hello " |
f"{number:05d}" | Zero padding | f"{42:05d}" | "00042" |
f"{value:.2e}" | Scientific notation | f"{1234567:.2e}" | "1.23e+06" |
"{}".format(var) | Format method | "Hello {}".format(name) | "Hello Alice" |
f"{var:05d}" | Zero padding | f"{42:05d}" | "00042" |
Test Your Knowledge
Test what you've learned about text formatting:
What's Next?
Now that you can format text professionally, you're ready to explore file operations. Learn how to read from and write to files, manage file systems, and persist data for your applications.
Ready to continue? Check out our lesson on File Operations.
Was this helpful?
Track Your Learning Progress
Sign in to bookmark tutorials and keep track of your learning journey.
Your progress is saved automatically as you read.