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:
.2ffixed decimals,,or_thousands separators,+always show sign,escientific,%percentage. - Integers in other bases:
bbinary,ooctal,x/Xhex,#adds a prefix;08pads with zeros. - Dates: datetime objects accept strftime codes, e.g.
{today:%d %b %Y}. - Conversions:
!ruses repr(),!suses 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
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}}")
Asha has 3 marks, best 92
Average: 85.00
ASHA passed
Set literal looks like {1, 2}
Width, alignment, numbers, bases and dates
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 "")
|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
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"))
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.