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:

:.2f
Format as float with 2 decimal places
3.14
:d
Format as integer
42
:e
Scientific notation
1.23e+02
:%
Percentage
75.50%
:,
Thousands separator
1,234,567
:>10
Right align in 10 characters
hello
:<10
Left align in 10 characters
hello
:^10
Center align in 10 characters
hello
:0>5
Pad with zeros, right align
00042
:x
Hexadecimal (lowercase)
ff
:X
Hexadecimal (uppercase)
FF
:b
Binary
1010

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})
%s
String
%d
Integer
%f
Float
%.2f
Float with 2 decimal places
%x
Hexadecimal
%o
Octal

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

Three Ways to Format — Use f-strings

StyleExampleVerdict
f-stringf"Hi {name}"Best — modern, fast, readable
.format()"Hi {}".format(name)OK — older code
% operator"Hi %s" % nameLegacy — avoid

Format Specifiers

After a colon inside { } you control width, precision, alignment, and more.

pi = 3.14159
price = 2500

print(f"{pi:.2f}")       # 3.14    -> 2 decimals
print(f"{price:,}")      # 2,500   -> thousands separator
print(f"{price:>8}")     # '    2500' -> right align width 8
print(f"{0.25:.0%}")     # 25%     -> percentage
print(f"{255:#x}")       # 0xff    -> hexadecimal
print(f"{42:04d}")       # 0042    -> zero-padded

Try It Yourself

Exercise 1: Format 1234.5678 with exactly two decimal places and a thousands separator.

Show solution
x = 1234.5678
print(f"{x:,.2f}")   # 1,234.57

Exercise 2: Print 0.875 as a whole-number percentage.

Show solution
print(f"{0.875:.0%}")   # 88%

Key Takeaways

  • Prefer f-strings — they embed expressions directly.
  • Control output with format specs: :.2f, :,, :>10, :%.
  • Padding and alignment make clean tabular text output.

📘 Real-World Deep Dive

Three formatting APIs exist: C-style <code>%</code>, <code>str.format</code>, and f-strings. F-strings are the obvious winner for new code: faster, more readable, and great for inline expressions.

Real-Life Scenario

A small log-emitter that formats size, time, percent, and structured outputs — using width/precision/alignment specifiers without breaking readability.

Real-Life Example

import time, datetime as dt
from decimal import Decimal

def fmt_bytes(n: int) -> str:
    for unit, div in [("GiB", 1024**3), ("MiB", 1024**2), ("KiB", 1024)]:
        if n >= div:
            return f"{n/div:8.2f} {unit}"
    return f"{n:>9d} B"

now = dt.datetime.now()
print(f"{now:%Y-%m-%d %H:%M:%S}  request_id={now.microsecond:06d}")
print(f"uploaded  : {fmt_bytes(15_728_640)}")
print(f"rate      : {0.8723:.2%}")
print(f"padding   : |{ 'aligned':<12} | {'right':>12} | {'center':^12} |")
total = Decimal("19.99")
print(f"price     : {total:.2f}")
print(f"hex       : {now.microsecond:08x}")

Expected Output

2026-08-20 21:48:30  request_id=214830
uploaded  :    15.00 MiB
rate      : 87.23%
padding   : |aligned      |        right |    center    |
price     : 19.99
hex       : 000347f6

Common mistakes

  • f"{x:.2f}" rounds on display, but x itself stays the original — don't confuse formatting with precision.
  • Mixing {user.name} with multi-line strings with { in literal text } produces a SyntaxError — escape with {{ / }}.
  • Width specifiers without alignment ({x:5}) right-align by default for numbers; left-align for strings.

🚀 Performance & Best Practices

  • F-strings compile to the fastest bytecode path; "{}".format(...) and % are slower.
  • Avoid formatting inside tight loops — format the final output once.
  • For thousand-separators use {x:,}; for fixed decimals, {x:.2f}; for percentages, {x:.2%}.

🧪 Try It Yourself

  1. Build a tabular print_row(*cells) helper that pads to the widest cell.
  2. Wrap a logger so messages render with fixed-width level + timestamp.
  3. Refactor an existing %-formatted message to f-string and benchmark.

FAQ: Python String Formatting

Common questions about this page.

What is Python String Formatting?

Python String Formatting is a Python Tutorial lesson that explains python string formatting in Python. Learn different methods to format strings in Python including f-strings, format(), and % formatting. Copy the samples and run them in the Python editor. It is written for beginners who want a clear definition and working examples.

Should I run python string formatting examples locally for better learning?

Yes. Use the browser editor on StudyGrid for a quick check, then Download the example and run it on your computer. Local runs show real errors and the real toolchain, which is one of the fastest ways to learn python string formatting in this Python Tutorial Python lesson (Python String Formatting).

How do I use python string formatting in Python?

To use python string formatting in Python, follow the examples on this StudyGrid page. Copy a snippet, run it in the browser, then Download and run it locally for better learning. Change the values and compare the output.

What is the syntax of python string formatting?

This Python String Formatting tutorial shows python string formatting syntax with short Python examples. Use the code blocks in this lesson for the exact statements, then try them in your editor.

Python String Formatting example for beginners

Yes. This page includes a beginner python string formatting example you can copy and run. It is designed for searches such as "python string formatting for beginners", "python string formatting example", and "how to use python string formatting".

What are common mistakes with python string formatting?

Common python string formatting mistakes include wrong syntax, mixing types, and skipping practice. Work through this Python Tutorial chapter in order, run every example, and check the output before moving on.

Why should I learn python string formatting?

Python String Formatting is used in real Python work. Learning python string formatting helps you write clearer programs and continue the Python Tutorial tutorial on StudyGrid.

Is Python String Formatting free to learn online?

Yes. You can learn python string formatting free on StudyGrid (studygrid.in). This chapter is part of the Python Tutorial path and includes examples, syntax, and next-step links.