Python’s new t-strings
What t-strings are
- t-strings (
t"...") look like f-strings but compile to aTemplateobject, not astr. - The Template contains:
- the literal string chunks, and
Interpolationobjects for each{expr}with the value, expression text, and format spec.
- Interpolations are evaluated immediately (like f-strings), but concatenation is deferred to library code.
Difference from f-strings / .format
- f-strings:
f"...{x}..." -> strimmediately; no trace of which parts were dynamic. - t-strings:
t"...{x}..." -> Template; a library can inspect each placeholder and decide how to render or escape it, or even not produce a string at all (e.g. build a DOM or SQL AST). - Conceptually: f-strings =
.formatdone at compile time; t-strings = “custom, pluggable.format” with full structure preserved.
Main use cases discussed
- SQL: replace
execute("... ? ...", (name,))withexecute(t"… WHERE name={name}"), letting the DB API build parameterized queries and prevent injection. - HTML: pass
t"<p>{evil}</p>"to a function that escapes values and/or builds a DOM. - Shell / subprocess (PEP 787): safely interpolate arguments into commands without shell injection.
- Logging:
log.debug(t"...{counter}...")lets the logger skip string construction when the log level is disabled.
Safety, typing, and API design
- Because Template is a different type from
strand intentionally lacks__str__, APIs can:- accept only Templates (and reject raw strings),
- separate “safe” (
execute(template)) and “unsafe” (execute_unsafe(str)) paths.
- Debate on backwards compatibility: existing DB APIs all take strings; options include adding new template-only methods, overloading with deprecation, or introducing “safe” variants.
- Some worry the tiny
fvstvisual difference is a footgun; others counter that type checkers and runtime type errors will catch misuse.
Syntax, tooling, and JS comparisons
- Some wanted JS-style tagged literals (
sql"SELECT…"/html"<p>…"), which would help syntax highlighting and type distinctions per language. - PEP explicitly rejected arbitrary user-defined prefixes; tooling is expected to infer context via types, annotations, or common call patterns (e.g.
html(t"...")). - Concerns about “yet another string prefix” and readability vs. arguments that prefixes enable richer editor support (embedded SQL/HTML linting).
Language complexity and philosophy
- Supporters see t-strings as a small, orthogonal feature solving real, long-standing security and ergonomics issues.
- Critics see them as more “syntax bloat” alongside many existing formatting mechanisms, moving Python further from “one obvious way” and toward feature creep.