说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
如果让我评选 Python 3.14 最值得学习的新特性,我会把 Template String Literals(模板字符串,简称 t-string) 排在前三。
它对应的是 PEP 750,乍一看和 f-string 很像,但实际上它解决的是 「字符串模板处理」 这个长期存在的问题,而不是字符串格式化。
Python 已经有三种常见字符串了:
name = "Tom"
# 普通字符串
"Hello"
# 格式化字符串
f"Hello {name}"
# 老的 Template
from string import Template
Template("Hello $name")
很多人第一反应就是:
f-string 已经够强了,为什么还要 t-string?
答案只有一句话:
f-string 的最终结果永远只是一个 str。
例如:
name = "Tom"
text = f"Hello {name}"
print(text)
输出:
Hello Tom
此时:
Python 已经忘记了:
!r:.2f全部变成了一个普通字符串。
而很多框架真正想要的是:
我希望知道:这里有一个变量,而不是已经拼接好的字符串。
例如:
HTML
html(f"<p>{user_input}</p>")
SQL
sql(f"SELECT * FROM user WHERE id={id}")
Shell
shell(f"rm {filename}")
日志
logger.info(f"User {user} login")
对于这些库来说:
它们已经拿不到变量的信息了。
只能看到:
"<p><script>...</script></p>"
于是只能:
既困难又不可靠。
Python 3.14 新增:
t"..."
例如:
name = "Alice"
tpl = t"Hello {name}"
注意:
这不是字符串。
而是:
type(tpl)
得到:
string.templatelib.Template
也就是说:
f-string
↓
表达式立即计算
↓
str
而:
t-string
↓
表达式计算
↓
Template对象
它保留了模板结构,而不是立即拼成字符串。
例如:
name = "Alice"
tpl = t"Hello {name}!"
可以直接遍历:
list(tpl)
结果类似:
[
"Hello ",
Interpolation(...),
"!"
]
官方文档中的示例也是如此:静态字符串与 Interpolation 对象交替出现。
可以理解成:
Template
├── "Hello "
├── {name}
└── "!"
而不是:
"Hello Alice!"
例如:
price = 12.345
tpl = t"¥{price:.2f}"
其中:
Interpolation
里面会保存:
value
↓
12.345
还有:
expression
↓
"price"
以及:
format_spec
↓
".2f"
还有:
conversion
↓
!r
!s
!a
等等。
也就是说:
Python 没有帮你格式化。
只是把:
:.2f
作为元数据保存下来,真正如何处理由模板处理器决定。
假设:
price = 12.3456
f"{price:.2f}"
立即得到:
"12.35"
所有信息丢失。
t"{price:.2f}"
得到:
Template
里面记录:
表达式:
price
值:
12.3456
format_spec:
".2f"
最后到底输出什么,
完全由你自己的函数决定。
官方给出的几个典型应用包括:安全 HTML、SQL、Shell、日志以及 DSL(领域特定语言)。
例如 HTML:
用户输入:
user = "<script>alert(1)</script>"
以前:
html(f"<p>{user}</p>")
html()
拿到的是:
"<p><script>...</script></p>"
已经不知道:
哪部分来自用户。
现在:
html(t"<p>{user}</p>")
html()
拿到的是:
静态:
<p>
变量:
user
值:
<script>...</script>
静态:
</p>
于是:
它可以:
只转义变量:
<p><script>...</p>
而不会把:
<p>
也一起转义。
官方文档给了一个有趣的小例子:
from string.templatelib import Interpolation
def render(template):
parts = []
for item in template:
if isinstance(item, Interpolation):
parts.append(str(item.value).upper())
else:
parts.append(item.lower())
return "".join(parts)
使用:
name = "Alice"
render(t"Hello {name}")
输出:
hello ALICE
整个过程完全由你决定如何处理静态文本和插值内容。
它并不是为了替代 f-string,而是为了让需要“理解模板结构”的库变得更简单、更安全。
例如:
| 场景 | 为什么适合 t-string |
|---|---|
| HTML 模板 | 自动转义变量,避免 XSS |
| SQL 构造 | 参数化处理,降低 SQL 注入风险 |
| Shell 命令 | 自动引用参数,减少命令注入风险 |
| 日志系统 | 保留变量信息,支持结构化日志 |
| DSL | 根据模板结构生成自定义对象,而不仅是字符串 |
如果只是:
print(f"Hello {name}")
或者:
path = f"/tmp/{filename}"
那么:
继续使用 f-string。
因为:
strt-string 的目标不是替代它,而是提供一种保留模板结构的新能力。
可以把三种字符串理解成下面这张表:
| 类型 | 前缀 | 返回值 | 适合场景 |
|---|---|---|---|
| 普通字符串 | "..." |
str |
固定文本 |
| f-string | f"..." |
str |
字符串格式化 |
| t-string(Python 3.14) | t"..." |
Template |
自定义模板处理、安全 HTML/SQL/Shell、结构化日志、DSL |
最核心的区别可以浓缩成一句话:
f-string 的使命是“生成字符串”,而 t-string 的使命是“保留模板”。 前者在插值后只留下最终文本;后者保留静态文本、插值表达式、格式说明等结构信息,让库和框架能够以安全、灵活的方式决定如何渲染或处理这些内容。
更新时间:2026-10-31 01:25:54 标签:python 模板字符串 字面值