摘要:自 Python 3.6 推出 f-字符串(Formatted String Literals)以来,开发者对其简洁、可读、功能强大的字符串格式化能力赞不绝口。但伴随而来的是滥用问题——许多人将 f-字符串直接用于处理用户输入,生成 SQL 或 HTML,从而
自 Python 3.6 推出 f-字符串(Formatted String Literals)以来,开发者对其简洁、可读、功能强大的字符串格式化能力赞不绝口。但伴随而来的是滥用问题——许多人将 f-字符串直接用于处理用户输入,生成 SQL 或 HTML,从而埋下注入风险。为此,Python 社区在 PEP 750 中提出了模板字符串(t-strings)特性,并已在 Python 3.14 中获得采纳,为更安全、更灵活的字符串处理打开新思路。
即时求值:f-字符串会在解析时将所有表达式计算并拼接成最终字符串,开发者无法在中间插入安全检查或转义逻辑。安全隐患:当用 f"SELECT * FROM users WHERE name = '{user}'" 生成 SQL 时,如果 user 带有恶意内容,就会导致 SQL 注入;同理,用 f"{user}" 拼接 HTML,很容易引发 XSS 攻击。可扩展性不足:f-字符串只会返回原生字符串,无法根据业务需求返回结构化对象或执行额外的渲染流程。延迟渲染:t-字符串不会立即生成字符串,而是返回一个 string.templatelib.Template 对象,开发者必须显式调用渲染函数。安全可控:Template 类型不实现 __str__,若未调用渲染函数就尝试转换为字符串,会得到不具备实际内容的默认输出,从根本上防止未受控的拼接。灵活扩展:基于 Template,可自由定义渲染函数,将模板输出为安全转义的字符串、结构化元素、数据库构造器乃至其他任意类型。模板字符串会将静态文本和动态插值分离,Template 对象提供三个核心接口:
strings:返回静态文本片段组成的元组,长度总比插值值多一项。values:返回所有插值值的元组,对应于相邻片段之间的动态内容。interpolations:返回包含更详细元信息的插值对象列表,每个对象可访问 value、expression、conversion、format_spec 等属性。from string.templatelib import Templatename = "World"template = t"Hello {name!s:>8}!"assert template.strings == ("Hello ", "!")assert template.values == ("World",)interp = template.interpolations[0]assert interp.expression == "name"assert interp.conversion == "s"assert interp.format_spec == ">8"通过这些接口,开发者可以在渲染前精准地获取并处理每处插值。
对于熟悉 JavaScript 标记模板(tagged template)的开发者,Python 的 t-字符串设计理念非常相似:在静态文本与插值之间传递上下文,由“标签”函数接手渲染逻辑。不同之处在于,Python 通过 string.templatelib.Template 类型,提供统一的 API 接口,并与现有静态类型系统、代码格式化工具更好地融合。
下面示例演示如何对 HTML 模板中的用户输入进行安全转义:
from string.templatelib import Templatedef html(template: Template) -> str:result = for item in template:if isinstance(item, str):result.append(item)else:# 假设 escape 为安全转义函数result.append(escape(item.value))return "".join(result)evil = "alert('bad')"template = t"{evil}
"safe = html(template)assert safe == "alert('bad')
"在渲染前统一对所有动态内容进行转义,确保最终输出绝无安全隐患。
t-字符串还能配合库返回自定义对象,而非简单字符串。例如,有的 HTML 工具会接收 Template 并输出 HTMLelement 对象:
attributes = {"src": "roquefort.jpg", "alt": "Yum"}template = t"借助这样的机制,标签属性的组装与类型校验都可在渲染函数中完成,提升了可读性与可维护性。
演示如何用 t-字符串实现“猪拉丁文”转换,只需遍历 Template 即可:
def pig_latin(template: Template) -> str:result = for item in template:if isinstance(item, str):result.append(item)else:word = item.valueif word and word[0] in "aeiou":result.append(word + "yay")else:result.append(word[1:] + word[0] + "ay")return "".join(result)name = "world"template = t"Hello {name}!"assert pig_latin(template) == "Hello orldway!"只要获取到静态与动态部分,就能根据业务需求进行任意转换,灵活性大幅提升。
致谢与社区贡献模板字符串的发展离不开社区的共同努力。感谢 Jim、Paul、Koudai、Lysandros、Guido 及众多讨论区成员对 PEP 750 的反馈与完善。正是他们的协作,使得 t-字符串这一特性得以顺利落地。
未来展望随着 Python 3.14 中 t-字符串的正式发布,生态工具与框架将迎来一系列适配与优化机会:
格式化工具:black、ruff 等可在 t-字符串内进行语法对齐与缩进。编辑器:VS Code、PyCharm 等可为常见模板(如 HTML、SQL)提供高亮。数据库构造:基于 Template 构建类型安全的 SQL 查询生成器。Web 框架:原生支持 t-字符串渲染,简化模板引擎使用。模板字符串(t-strings)作为 PEP 750 的核心成果,将在 Python 3.14 中为开发者带来更安全、更灵活的字符串处理范式。无论是防御注入攻击,还是构建跨类型渲染管道,t-字符串都展现出无限潜能。让我们一同拥抱这一特性,在未来项目中尽情发挥它的力量!
来源:高效码农