Mojo String Formatting

String formatting builds readable output by combining text with variable values. Instead of concatenating pieces manually with many + operators, formatting methods let you place values directly inside a template string. Mojo provides several approaches — from simple concatenation to Python-style format strings via Python interop.

The Envelope Analogy

Template:  "Dear {name}, your balance is {amount}."

Before filling:
  "Dear {name}, your balance is {amount}."
          ↑                        ↑
       placeholder               placeholder

After filling (name="Alice", amount=150.0):
  "Dear Alice, your balance is 150.0."

Formatting inserts values into placeholders without manual string joins.

Basic Concatenation (Simple Cases)

fn main():
    var name = "Mojo"
    var version = 1
    var message = "Language: " + name + " v" + String(version)
    print(message)   # Language: Mojo v1

Concatenation works for short strings. It becomes messy with many values — use formatted approaches for anything with three or more insertions.

Building Formatted Strings with String()

fn format_score(player: String, score: Int, rank: Int) -> String:
    return player + " | Score: " + String(score) + " | Rank: " + String(rank)

fn main():
    print(format_score("Alice", 9500, 1))   # Alice | Score: 9500 | Rank: 1
    print(format_score("Bob",   8200, 2))   # Bob   | Score: 8200 | Rank: 2

Python f-Strings via Interop

Mojo's Python interop lets you use Python's powerful f-string formatting for complex output patterns.

from python import Python

fn main() raises:
    var py = Python.import_module("builtins")

    var name   = "Alice"
    var score  = 95.7
    var grade  = "A"

    # Use Python's format() function
    var result = py.str("Name: {}, Score: {:.1f}, Grade: {}").format(
        name, score, grade
    )
    print(result)   # Name: Alice, Score: 95.7, Grade: A

Number Formatting

Decimal Places

from python import Python

fn main() raises:
    var py = Python.import_module("builtins")

    var pi = 3.141592653589793

    # Round to 2 decimal places
    var two_dp = py.str("{:.2f}").format(pi)
    print(two_dp)    # 3.14

    # Round to 4 decimal places
    var four_dp = py.str("{:.4f}").format(pi)
    print(four_dp)   # 3.1416

Thousands Separator

from python import Python

fn main() raises:
    var py = Python.import_module("builtins")
    var big = 1234567890
    print(py.str("{:,}").format(big))    # 1,234,567,890
    print(py.str("{:_}").format(big))    # 1_234_567_890

Zero Padding and Width

from python import Python

fn main() raises:
    var py = Python.import_module("builtins")

    # Pad number to 5 characters with zeros
    for i in range(1, 6):
        print(py.str("{:05d}").format(i))

Output:

00001
00002
00003
00004
00005

Table Formatting

from python import Python

fn main() raises:
    var py = Python.import_module("builtins")

    # Column widths: name=15, score=8, grade=6
    var header = py.str("{:<15} {:>8} {:>6}").format("Name", "Score", "Grade")
    print(str(header))
    print("-" * 31)

    var rows = [("Alice", 95, "A"), ("Bob", 82, "B"), ("Carol", 74, "C")]
    for row in rows:
        var line = py.str("{:<15} {:>8} {:>6}").format(
            row[0], row[1], row[2]
        )
        print(str(line))

Output:

Name              Score  Grade
-------------------------------
Alice                95      A
Bob                  82      B
Carol                74      C
Alignment codes:
  {:<15}  left-align in field of width 15
  {:>8}   right-align in field of width 8
  {:^10}  center in field of width 10

Building a Mojo Format Helper

Wrap common formatting into a reusable Mojo function so you do not repeat the Python interop boilerplate.

from python import Python

fn fmt(template: String, *args: PythonObject) raises -> String:
    var py = Python.import_module("builtins")
    var result = py.str(template).format(*args)
    return str(result)

fn main() raises:
    print(fmt("Hello, {}!", "Mojo"))
    print(fmt("{} + {} = {}", 3, 4, 7))
    print(fmt("Pi ≈ {:.4f}", 3.14159))

Output:

Hello, Mojo!
3 + 4 = 7
Pi ≈ 3.1416

Formatting for Debugging

fn debug_vector(label: String, data: List[Float64]):
    print(label + ": [", end="")
    for i in range(len(data)):
        if i > 0:
            print(", ", end="")
        print(data[i], end="")
    print("]")

fn main():
    var weights = List[Float64](0.12, 0.47, 0.85, 0.33)
    debug_vector("weights", weights)
    # weights: [0.12, 0.47, 0.85, 0.33]

Format Specification Mini-Language

{[fill][align][sign][width][grouping][.precision][type]}

type codes:
  d  → integer         {:d}     → 42
  f  → fixed float     {:.2f}   → 3.14
  e  → scientific      {:.2e}   → 3.14e+00
  %  → percentage      {:.1%}   → 31.4%
  s  → string          {:s}     → hello
  b  → binary          {:b}     → 101010
  x  → hexadecimal     {:x}     → 2a
  o  → octal           {:o}     → 52

Examples:
  "{:08b}".format(42)   → "00101010"
  "{:.2e}".format(12345) → "1.23e+04"
  "{:.1%}".format(0.856) → "85.6%"

Key Takeaways

Simple string concatenation with + and String() handles short output. Python f-string format via py.str("{...}").format(...) handles complex templates with alignment, padding, and precision. Use :<, :>, and :^ for left, right, and center alignment in fixed-width columns. Use :.Nf for N decimal places and :, for thousands separators. Wrap repeated formatting patterns in a helper function to keep call sites clean. The Python format mini-language is available in full through Mojo's Python interop layer.

Leave a Comment

Your email address will not be published. Required fields are marked *