✨ 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.

python
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 TypePurposeExampleResult
f"{var}"F-string variable insertionf"Hello {name}""Hello Alice"
f"{value:.2f}"Decimal placesf"{3.14159:.2f}""3.14"
f"{value:,}"Thousands separatorf"{1234567:,}""1,234,567"
f"{value:.1%}"Percentagef"{0.123:.1%}""12.3%"
f"{text:<10}"Left alignf"{'hello':<10}""hello "
f"{text:>10}"Right alignf"{'hello':>10}"" hello"
f"{text:^10}"Center alignf"{'hello':^10}"" hello "
f"{number:05d}"Zero paddingf"{42:05d}""00042"
f"{value:.2e}"Scientific notationf"{1234567:.2e}""1.23e+06"
"{}".format(var)Format method"Hello {}".format(name)"Hello Alice"
f"{var:05d}"Zero paddingf"{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?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent