Python 的新型 t-string

admin 2025年4月22日23:59:15评论1 views字数 2954阅读9分50秒阅读模式

模板字符串,也被称为 t-string,已被正式接纳为 Python 3.14 的一项特性,该版本将于 2025 年底发布。🎉

我对此感到兴奋;t-string为 Python 中更安全、更灵活的字符串处理打开了大门。

t-string的核心思想是什么?

自 Python 3.6 引入以来,f-string已成为一种非常流行的字符串格式化方式。它们简洁、可读且功能强大。

事实上,它们非常方便,以至于许多开发者将 f-string用于一切... 即使在不应该使用它们的时候!

然而,f-string经常被危险地(误)用于格式化包含用户输入的字符串。我曾见过 f-string被用于 SQL (f"SELECT * FROM users WHERE name = '{user_name}'") 和 HTML (f"<div>{user_name}</div>")。这些做法不安全!如果user_name包含恶意值,可能导致 SQL 注入或跨站脚本攻击(XSS)。

模板字符串是 Python 的 f-string的泛化。f-string会立即变成一个字符串,而 t-string会解析为一个新的类型,string.templatelib.Template

from string.templatelib import Templatename = "World"templateTemplate = t"Hello {name}!"

重要的是,Template 实例并非字符串。Template 类型不提供其自身的__str__()实现,也就是说,调用str(my_template)不会返回有用的值。模板在使用前必须经过处理;这个处理代码可以由开发者编写,也可以由库提供,并且可以安全地转义动态内容。

我们可以想象一个库提供一个html()函数,它接受一个 Template 并返回一个安全转义后的字符串:

evil = "<script>alert('bad')</script>"template = t"<p>{evil}</p>"safe = html(template)assert safe == "<p>&lt;script&gt;alert('bad')&lt;/script&gt;</p>"

当然,t-string的用途不仅仅是安全;它们还允许更灵活的字符串处理。例如,html()函数可以返回一个新的类型,HTMLElement。它还可以接受 HTML 本身中各种有用的替换项:

attributes = {"src""roquefort.jpg""alt""Yum"}template = t"<img {attributes} />"element = html(template)assert str(element) == "<img src='roquefort.jpg' alt='Yum' />"

如果你使用过 JavaScript,t-string可能会让你感到熟悉。它们是 JavaScript 标签模板 (tagged templates) 的 Pythonic 对应物。

如何使用 t-string?

为了支持处理,Template 提供了对其字符串部分和插值值(在它们组合成最终字符串之前)的访问权限。

Template 的.strings.values属性返回元组:

name = "World"template = t"Hello {name}!"assert template.strings == ("Hello ""!")assert template.values == (name,)

字符串的数量总是比值的数量多一个(字符串可能为空)。也就是说,t"".strings == ("",)t"{name}".strings == ("", "")

作为一种快捷方式,Template 也可以被迭代:

name = "World"template = t"Hello {name}!"contents = list(template)assert contents[0] == "Hello "assert contents[1].value == nameassert contents[2] == "!"

编写复杂处理代码的开发者还可以访问每个插值的详细细节:

name = "World"template = t"Hello {name!s:>8}!"assert template.interpolations[0].value == nameassert template.interpolations[0].expression == "name"assert template.interpolations[0].conversion == "s"assert template.interpolations[0].format_spec == ">8"

除了支持字面形式 (t"foo"),Template 也可以直接实例化:

from string.templatelib import TemplateInterpolationtemplate = Template("Hello ",Interpolation(value="World", expression="name"),"!")

字符串和插值项可以以任何顺序提供给 Template 构造函数。

一个简单的 t-string示例

假设我们想编写代码将所有被替换的词转换为猪拉丁语。只需一个简单的函数即可:

def pig_latin(template: Template) -> str:"""Convert a Template to pig latin."""result = []for item in template:if isinstance(item, str):result.append(item)else:word = item.valueif word and word[0in "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!"

这是一个简单的例子;如果你想看一些不那么傻的例子,请查看PEP 750 示例仓库。

t-string发布后会发生什么?

t-string是一项强大的新特性,将使 Python 字符串处理更加安全和灵活。我希望看到它们在各种库和框架中使用,尤其是那些处理用户输入的。

此外,我希望工具生态系统能够适应并支持 t-string。例如,我希望看到 black 和 ruff 格式化 t-string的内容,并且 vscode 对这些内容进行语法高亮,如果它们是常见的类型,如 HTML 或 SQL。

很高兴能在这个项目上与 Jim、Paul、Koudai、Lysandros 和 Guido 认识并合作,并与 Python 社区的许多其他成员在线互动,没有他们的意见,PEP 750 根本无法成型。我迫不及待地想看到开发者们在 t-string发布后会构建出什么!

原文始发于微信公众号(知机安全):Python 的新型 t-string

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月22日23:59:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Python 的新型 t-stringhttp://cn-sec.com/archives/3986216.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息