Course topics

By WebNest Studio

Python Tutorial

String Formatting in Python

Turning values into well-presented text is something every program does: invoices, reports, log messages, emails, table output. Python offers three formatting systems — f-strings (the modern standard), str.format(), and the old % operator — plus string.Template for user-supplied templates.

This lesson covers all of them with the format specification mini-language: widths, alignment, precision, thousands separators, percentages, dates, number bases and debugging with =.

f-Strings

Prefix a string with f and put expressions in braces: f"{name} is {age + 1}". Any expression works, including method calls and conditional expressions. Since Python 3.12 you can reuse the same quote type inside the braces and write multi-line expressions. Use {{ and }} for literal braces.

The Format Specification Mini-Language

After a colon, a format spec controls output: [[fill]align][sign][width][,][.precision][type].

  • Alignment: < left, > right, ^ centre, with an optional fill character ({x:*^10}).
  • Numbers: .2f fixed decimals, , or _ thousands separators, + always show sign, e scientific, % percentage.
  • Integers in other bases: b binary, o octal, x/X hex, # adds a prefix; 08 pads with zeros.
  • Dates: datetime objects accept strftime codes, e.g. {today:%d %b %Y}.
  • Conversions: !r uses repr(), !s uses str(); {x=} shows the expression and value.

str.format(), % and Template

"{} scored {:.1f}".format(name, score) uses the same mini-language and is useful when the template is stored separately from the values. The % operator ("%s is %d" % (name, age)) is legacy but still appears in older code and logging. string.Template("Hello $name") is the safe choice when end users write templates, because it cannot evaluate arbitrary expressions.

Examples

f-string expressions and literal braces

Python
name, marks = "Asha", [78, 92, 85]
print(f"{name} has {len(marks)} marks, best {max(marks)}")
print(f"Average: {sum(marks) / len(marks):.2f}")
print(f"{name.upper()} {'passed' if min(marks) >= 40 else 'failed'}")
print(f"Set literal looks like {{1, 2}}")
Output
Asha has 3 marks, best 92
Average: 85.00
ASHA passed
Set literal looks like {1, 2}

Width, alignment, numbers, bases and dates

Python
from datetime import date

print(f"|{'left':<10}|{'right':>10}|{'mid':^10}|{'fill':*^10}|")
print(f"{1234567.891:,.2f}  {1234567:_}  {-42:+}  {42:+}")
print(f"{0.4567:.1%}  {12345.678:.2e}  {7:03d}")
print(f"{255:b} {255:o} {255:x} {255:X} {255:#x} {5:08b}")
d = date(2026, 9, 27)
print(f"{d:%d %B %Y} | {d:%a %d/%m/%y}")
value = 3.14159
print(f"{value=:.2f}  {name!r}" if (name := "Ravi") else "")
Output
|left      |     right|   mid    |***fill***|
1,234,567.89  1_234_567  -42  +42
45.7%  1.23e+04  007
11111111 377 ff FF 0xff 00000101
27 September 2026 | Sun 27/09/26
value=3.14  'Ravi'

str.format(), % formatting and string.Template

Python
from string import Template

template = "{name:<8}|{score:>6.1f}|{grade:^5}"
for row in [("Asha", 91.456, "A"), ("Ravi", 67.0, "C")]:
    print(template.format(name=row[0], score=row[1], grade=row[2]))

print("%s is %d years old and %.1f%% done" % ("Meera", 24, 87.25))

t = Template("Dear $name, your order $$${amount} has shipped.")
print(t.substitute(name="Asha", amount="2,999"))
print(Template("Hi $name, $missing").safe_substitute(name="Ravi"))
Output
Asha    |  91.5|  A
Ravi    |  67.0|  C
Meera is 24 years old and 87.2% done
Dear Asha, your order $2,999 has shipped.
Hi Ravi, $missing

Common Mistakes

  • Concatenating with + and str() instead of using f-strings.
  • Formatting money as {x:.2} (2 significant digits) instead of {x:.2f} (2 decimals).
  • Letting users supply str.format() templates, which can access object attributes; use string.Template.
  • Forgetting to double braces ({{ }}) when a literal brace is needed in an f-string.

Key Points to Remember

  • f-strings are the modern, fastest, most readable way to format.
  • Format specs control fill/alignment, width, separators, precision, type, base and dates.
  • {x=} and !r help with debugging output.
  • str.format() suits stored templates; % is legacy; string.Template is safe for user templates.

Practice the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.