Python - String Padding (ljust, rjust, center, zfill)

• Python provides four built-in string methods for padding: `ljust()` and `rjust()` for left/right alignment, `center()` for centering, and `zfill()` specifically for zero-padding numbers

Key Insights

• Python provides four built-in string methods for padding: ljust() and rjust() for left/right alignment, center() for centering, and zfill() specifically for zero-padding numbers • All padding methods return new strings without modifying the original, and they accept optional fill characters (defaulting to spaces, except zfill() which uses zeros) • Understanding when to use each method—from formatting tabular output to preparing numeric strings for sorting or display—is essential for clean, readable code

Basic String Padding with ljust() and rjust()

The ljust() and rjust() methods pad strings to a specified width by adding characters to the right or left respectively. If the string is already longer than the specified width, the original string is returned unchanged.

# Left justify (pad on the right)
text = "Python"
padded = text.ljust(10)
print(f"'{padded}'")  # 'Python    '
print(len(padded))     # 10

# Right justify (pad on the left)
padded = text.rjust(10)
print(f"'{padded}'")  # '    Python'

# Custom fill character
padded = text.ljust(10, '-')
print(f"'{padded}'")  # 'Python----'

padded = text.rjust(10, '*')
print(f"'{padded}'")  # '****Python'

These methods are particularly useful for creating aligned columns in console output:

products = [
    ("Laptop", 1299.99),
    ("Mouse", 24.50),
    ("Keyboard", 89.00),
    ("Monitor", 449.99)
]

print("Product".ljust(15) + "Price".rjust(10))
print("-" * 25)

for name, price in products:
    print(name.ljust(15) + f"${price:.2f}".rjust(10))

Output:

Product              Price
-------------------------
Laptop            $1299.99
Mouse               $24.50
Keyboard            $89.00
Monitor            $449.99

Centering Text with center()

The center() method distributes padding equally on both sides of a string. When the padding cannot be evenly distributed, the extra character goes to the right side.

title = "Report"

# Basic centering
centered = title.center(20)
print(f"'{centered}'")  # '       Report       '

# Custom fill character
centered = title.center(20, '=')
print(centered)  # '=======Report======='

# Odd padding distribution
text = "Hi"
print(f"'{text.center(7)}'")   # '  Hi   ' (3 spaces left, 2 right)
print(f"'{text.center(8)}'")   # '   Hi   ' (3 spaces each side)

Common use case for headers and banners:

def print_section(title, width=50):
    print(title.center(width, '='))
    
print_section("Configuration Settings")
print("debug_mode: true")
print("max_connections: 100")
print()
print_section("Database Information")
print("host: localhost")
print("port: 5432")

Output:

============Configuration Settings=============
debug_mode: true
max_connections: 100

=============Database Information==============
host: localhost
port: 5432

Zero-Padding Numbers with zfill()

The zfill() method is specifically designed for numeric strings, padding with zeros on the left. It intelligently handles positive and negative signs, placing them before the zeros.

# Basic zero-padding
num = "42"
print(num.zfill(5))      # '00042'

# Handles signs correctly
positive = "+123"
negative = "-456"
print(positive.zfill(8))  # '+0000123'
print(negative.zfill(8))  # '-0000456'

# Already long enough
long_num = "123456"
print(long_num.zfill(4))  # '123456' (unchanged)

Practical applications include file naming, ID generation, and data formatting:

# Generate sequential filenames
for i in range(1, 15):
    filename = f"image_{str(i).zfill(4)}.jpg"
    print(filename)
# image_0001.jpg
# image_0002.jpg
# ...
# image_0014.jpg

# Format invoice numbers
def format_invoice(year, sequence):
    return f"INV-{year}-{str(sequence).zfill(6)}"

print(format_invoice(2024, 1))      # INV-2024-000001
print(format_invoice(2024, 1523))   # INV-2024-001523

Unlike rjust(), zfill() only works with zeros and is aware of numeric formatting:

# zfill() vs rjust() with numbers
value = "-42.5"

# zfill handles the sign
print(value.zfill(10))        # '-000042.5'

# rjust doesn't understand numeric context
print(value.rjust(10, '0'))   # '0000-42.5' (wrong placement)

Handling Edge Cases and Unicode

All padding methods work with Unicode characters, but be aware of character width in terminal displays:

# Unicode fill characters
text = "Hello"
print(text.center(15, '•'))   # '•••••Hello•••••'
print(text.center(15, '→'))   # '→→→→→Hello→→→→→'

# Emoji (single character, but may display wider)
print(text.center(15, '🎯'))  # '🎯🎯🎯🎯🎯Hello🎯🎯🎯🎯🎯'

Empty strings and edge cases:

# Empty string
empty = ""
print(f"'{empty.ljust(5)}'")    # '     '
print(f"'{empty.center(5)}'")   # '     '
print(f"'{empty.zfill(5)}'")    # '00000'

# Width of zero or negative (returns original)
text = "Python"
print(text.ljust(0))    # 'Python'
print(text.rjust(-5))   # 'Python'

Performance Considerations

String padding creates new string objects. For high-frequency operations, consider alternatives:

import timeit

# Padding many strings
def using_ljust():
    return [str(i).ljust(10) for i in range(1000)]

def using_format():
    return [f"{i:<10}" for i in range(1000)]

def using_format_spec():
    return [format(i, '<10') for i in range(1000)]

# All perform similarly, choose based on readability
print(timeit.timeit(using_ljust, number=1000))
print(timeit.timeit(using_format, number=1000))
print(timeit.timeit(using_format_spec, number=1000))

For building large padded strings, use a list and join:

# Inefficient
result = ""
for i in range(1000):
    result += str(i).zfill(6) + "\n"

# Efficient
lines = [str(i).zfill(6) for i in range(1000)]
result = "\n".join(lines)

Combining Padding Methods

Real-world scenarios often require combining multiple techniques:

# Create a formatted table with mixed alignment
def print_sales_report(data):
    # Header
    headers = ["ID", "Product", "Quantity", "Price", "Total"]
    widths = [6, 20, 10, 10, 12]
    alignments = [str.center, str.ljust, str.rjust, str.rjust, str.rjust]
    
    # Print header
    header_row = ""
    for header, width, align in zip(headers, widths, alignments):
        header_row += align(header, width)
    print(header_row)
    print("=" * sum(widths))
    
    # Print data
    for row in data:
        row_str = ""
        row_str += str(row['id']).zfill(4).center(widths[0])
        row_str += row['product'].ljust(widths[1])
        row_str += str(row['qty']).rjust(widths[2])
        row_str += f"${row['price']:.2f}".rjust(widths[3])
        row_str += f"${row['total']:.2f}".rjust(widths[4])
        print(row_str)

sales_data = [
    {'id': 1, 'product': 'Laptop', 'qty': 2, 'price': 1299.99, 'total': 2599.98},
    {'id': 42, 'product': 'USB Cable', 'qty': 10, 'price': 5.99, 'total': 59.90},
    {'id': 103, 'product': 'Monitor', 'qty': 1, 'price': 449.99, 'total': 449.99}
]

print_sales_report(sales_data)

Output:

  ID  Product                  Quantity     Price       Total
==========================================================
 0001 Laptop                          2  $1299.99    $2599.98
 0042 USB Cable                      10     $5.99      $59.90
 0103 Monitor                         1   $449.99     $449.99

Alternatives and Modern Approaches

While padding methods remain useful, f-strings and format() provide more concise syntax:

name = "Alice"
score = 95

# Using padding methods
print(name.ljust(10) + str(score).rjust(5))

# Using f-strings (more readable)
print(f"{name:<10}{score:>5}")

# Format specifiers
print(f"{name:_<10}{score:0>5}")  # Custom fill chars
# Alice_____00095

# Combining with other formatting
value = 1234.5
print(f"{value:0>10.2f}")  # '0001234.50'

The padding methods excel when you need to pad existing strings programmatically or when working with string variables where f-string formatting would be awkward. Choose based on context and readability requirements.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.