Overview

Use f-strings by default; use str.format when the template is data (a config value or translation); keep % only for logging calls. Python 3.14 adds t-strings for safe interpolation into HTML, SQL, and shell.

Which one

Use f-strings by default and % only for logging.

StyleExampleUse when
f-stringf"{name} is {age}"Template is literal code.
str.format"{0} {name}".format(a, name=b)Template is a runtime string.
format_map"{x}".format_map(d)Values come from one mapping; a __missing__ method can supply defaults.
%log.info("x=%s", x)logging, which formats lazily and only if the record is emitted.
t-string (3.14+)t"Hi {name}"You need a string.templatelib.Template, not a str, so a library can escape each value.

str.format, percent, and custom formats

Use these forms when the template is not a literal.

FormExample
Reuse or unpack"{0} {0}".format(a), "{x}".format(**d)
Attribute or item access"{0.name}".format(obj), "{0[key]}".format(d)
Percent codes"%s", "%d", "%.2f", "%r", "%(key)s" % d
Custom specformat(obj, "spec") calls obj.__format__("spec"); implement it to embed domain objects in f-strings.

f-string features

Use = for debug output and nested specs for dynamic widths.

PatternExampleOutput
Self-documenting (3.8+)f"{value=}"value=42
Conversionf"{obj!r}", !s, !arepr, str, ascii
Dynamic width and precisionf"{x:{width}.{prec}f}" 3.142
Datef"{dt:%Y-%m-%d %H:%M}"2026-05-14 09:30
Nested quotesf"{d['k']}"Use a different quote inside; Python 3.12+ lifts this limit.

Format spec

Grammar after the colon: [[fill]align][sign][z][#][0][width][grouping][.precision][type].

SpecExampleOutput
.2ff"{3.14159:.2f}"3.14
, / _ groupingf"{1000000:,}"1,000,000 / 1_000_000 with _
.1%f"{0.42:.1%}"42.0%
.2ef"{12345.6:.2e}"1.23e+04
08df"{42:08d}"00000042
>10, <10, ^10f"{'hi':>10}"Right, left, center in width 10.
+df"{42:+d}"+42
x, #x, bf"{255:#x}"0xff (also b binary, o octal)

Gotchas

Avoid these; each evaluates too early or too late, or interpolates untrusted input.

GotchaFix
An f-string is evaluated where it is written, not when it is used.Use str.format or a function for deferred templates.
Before Python 3.12, backslashes and reused quote types are not allowed inside {}.Compute the value first, or alternate quote types.
f"..." in a logging call formats even when the log is dropped.Pass arguments: log.info("x=%s", x).
"%s" % value breaks when value is a tuple.Write "%s" % (value,).
Formatting a float rounds for display only.Call round() if you need the rounded value.
Spec type n depends on the current locale.Use , or _ for portable output.
Never build SQL, HTML, or shell commands with f-strings from user input.Use parameterized queries, escaping, or a t-string-aware library.