当前位置:首页 > 文章列表 > 文章 > python教程 > Python 3.14 template strings 怎样延迟格式化

Python 3.14 template strings 怎样延迟格式化

来源:17golang原创 2026-11-03 11:33:04 0浏览 收藏

如果你把 f-string 写成 f"用户 {name}",Python 会立即得到一段普通字符串;当输出规则不止一种时,静态文本和动态值已经被拼在一起,后续很难再区分。Python 3.14 的 template strings(t-string)解决的是这个边界:它仍然立即计算花括号里的表达式,但返回 string.templatelib.Template,把静态片段、插值值、转换标记和格式说明保留下来,等真正渲染时再决定怎么组合。

所以标题里的“延迟格式化”要准确理解为“延迟把 Template 渲染成最终文本”,不是延迟读取变量或延迟执行表达式。下面从最小示例开始,写一个可以复用的渲染器。

先看 t-string 到底延迟了什么

Python 3.14 使用 t 前缀,语法看起来和 f-string 很像。区别在于返回值不是 str,而是一个不可变的 Template。Template 里保存了静态字符串元组和插值元组,插值对象还带有原始表达式、转换方式和格式说明。

from string.templatelib import Interpolation

name = "Ada"
amount = 12.5
template = t"用户 {name!s} 本次消费 {amount:.2f} 元"

# t-string 会先求出 name 和 amount,但暂时不按规则拼成最终文本。
print(type(template).__name__)
print(template.strings)
print(template.values)

for item in template:
    # 通过类型区分静态片段和花括号中的动态插值。
    if isinstance(item, Interpolation):
        print("插值:", item.expression, item.conversion, item.format_spec)
    else:
        print("静态片段:", item)

这里的关键是:template.values 已经包含表达式的求值结果,因此不能把 t-string 当作保存变量名、稍后重新读取变量的惰性容器。如果 name 在创建 Template 后改变,原来的插值对象不会自动跟着改变。

Python t-string 将静态片段与插值对象放在 Template 中的结构说明图
图1:结构说明图,展示 Template、静态字符串和 Interpolation 之间的静态关系;这是原创说明图,不是运行截图。

读取 strings、interpolations 和 values

Template 的三组数据分别适合不同用途:

  • strings:只包含静态文本,数量总是比插值多一个,连续插值之间可能出现空字符串。
  • interpolations:保存每个花括号表达式对应的 Interpolation 对象。
  • values:只是所有插值的 value 组成的元组,适合快速读取值,不保留格式元数据。

如果要实现自定义格式化,应优先遍历 Template 本身,因为迭代结果已经按原始顺序交错给出静态片段和插值对象。空的静态片段不会从迭代结果中产生,但它仍然存在于 strings 中。

from string.templatelib import Interpolation

product = "键盘"
count = 2
template = t"商品 {product} 数量 {count:02d}"

# 这里不直接 str(template),而是保留每个部分,等待渲染策略决定输出格式。
for part in template:
    if isinstance(part, Interpolation):
        print({
            "expression": part.expression,
            "value": part.value,
            "conversion": part.conversion,
            "format_spec": part.format_spec,
        })
    else:
        print({"literal": part})

按需渲染:把格式化放到调用时

下面的函数模拟 f-string 的常规语义,但渲染时机由调用者决定。它先处理 !s、!r 和 !a,再把格式说明交给 format(),最后把各段拼成字符串。

from string.templatelib import Interpolation, Template, convert

def render(template: Template) -> str:
    parts: list[str] = []
    for item in template:
        if isinstance(item, Interpolation):
            # 先按 !s、!r 或 !a 转换,再应用格式说明。
            value = convert(item.value, item.conversion)
            parts.append(format(value, item.format_spec))
        else:
            # 静态片段原样保留,避免改变模板的文字结构。
            parts.append(item)
    return "".join(parts)

user = "Ada"
score = 9.5
message = t"{user} 的得分是 {score:.1f}"

# Template 创建后先保留结构;真正需要日志或响应时才渲染。
print(render(message))

这个例子里的“按需”是业务代码选择何时调用 render()。如果一次请求只需要结构化字段,可以不调用它,直接读取插值对象;如果需要人类可读日志,再调用渲染器输出文本。Template 本身没有专用的 __str__(),这是因为它并不存在唯一正确的字符串化方式。

Python t-string 在渲染策略中按转换和格式说明生成文本的结构说明图
图2:关系说明图,展示 Template 经过自定义渲染器读取 Interpolation 后形成最终文本;这是原创说明图,不是运行截图。

转换、格式说明和安全边界

t-string 不会自动替你执行最终格式化。{value!r} 的 conversion 会记录为 "r",{value:.2f} 的 format_spec 会记录为 ".2f",实际如何解释它们由处理 Template 的代码决定。上面的 render() 选择了与 f-string 接近的行为,但你也可以在这里增加业务规则。

例如生成 HTML 时,应该在渲染器中对用户输入做 HTML 转义;生成 SQL 时仍然应该使用数据库驱动提供的参数化接口,而不是把 t-string 当成自动防注入工具。t-string 只是让你在静态片段和动态值合并前拥有处理机会,安全性取决于处理器是否按目标语境正确编码。

还要注意两个边界:

  • 插值表达式会在 t-string 创建时从左到右求值,耗时函数、异常和副作用不会被推迟。
  • Template 与普通 str 不能直接拼接,因为 Python 无法猜测这个字符串应该算静态片段还是动态插值;需要显式使用 Template() 或 Interpolation()。

什么时候值得使用 t-string

如果只是拼出一次普通提示语,f-string 更简单;如果需要在合并前识别字段、保留表达式元数据、输出人类文本和结构化数据两种结果,t-string 才有明显价值。

场景建议原因
一次性普通字符串继续使用 f-string无需额外处理 Template
结构化日志使用 t-string + 自定义 formatter可同时读取可读文本与字段值
HTML 或轻量 DSL使用 t-string + 语境专用渲染器能在合并前转义和校验动态值
想延迟执行变量表达式不要使用 t-string插值表达式仍然立即求值

总结一下:Python 3.14 template strings 延迟的是“如何把已经求值的静态片段和插值对象渲染成结果”,而不是延迟求值。掌握 Template、Interpolation、conversion 和 format_spec 四个部分,就可以把同一份模板分别用于日志、HTML 或其他自定义输出。

常见问题

t-string 能替代所有 f-string 吗?

不能。t-string 返回 Template,调用方必须提供处理逻辑;只需要一次普通字符串时,f-string 更直接。

Template 能直接 print 吗?

不应依赖隐式字符串化。Template 没有专用的 __str__(),应显式调用自己的渲染函数,或者把它交给专门的 formatter。

t-string 会自动转义 HTML 或 SQL 吗?

不会。它只提供合并前的结构访问能力,转义、参数绑定和安全策略必须由目标语境的处理器负责。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Java ExecutorService shutdownNow 怎样处理未完成任务Java ExecutorService shutdownNow 怎样处理未完成任务
上一篇
Java ExecutorService shutdownNow 怎样处理未完成任务
Python typing.ReadOnly 怎样标记 TypedDict 中不可修改字段
下一篇
Python typing.ReadOnly 怎样标记 TypedDict 中不可修改字段
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    857次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    861次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    938次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    918次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    747次使用