Python最近出了个大新闻:PEP-750t-string语法被正式采纳了!这意味着Python将在今年10月发布的3.14版本中引入一种新的字符串前缀t,称为模板字符串(TemplateStrings),即t-string。这是继f-string之后,字符串处理能力的重大升级,旨在授予更安全、更优美轻盈的字符串插值处理机制。t-string的高度发展语法与f-string非常反对,但得到的结果却大为不同:name=World#f-string语法formatted=fHello{name}!print(type(formatted))#输出:class'str'print(formatted)#输出:HelloWorld!#t-string语法templated=tHello{name}!print(type(templated))#输出:class'string.templatelib.Template'print(templated.strings)#输出:('Hello','')print(templated.interpolations[0].value)#输出:Worldprint(.join(itemifisinstance(item,str)elsestr(item.value)foritemintemplated))#输出:HelloWorld!复制代码如上所述,t-string与f-string不反对是,它不会立即得到普通字符串,而是返回一个新的类型Template(来自Python3.14新增的标准库模块string.templatelib)。这个类型不能直接作为普通字符串输出,但它授予了对字符串和其内部插值表达式的结构化访问,使得开发者能够在字符串组合拔出值前添加拦截和转换。一句话总结t-string的不次要的部分特点就是延迟渲染。为什么要设计t-string?f-string因其简洁易用而广受避免/重新确认/支持,但它也存在一些无法关心的局限性:安全隐患:当直接将用户输入嵌入到SQL查询、HTML内容或系统命令中时,f-string可能导致收回攻击缺乏转换能力:f-string没有授予在字符串组合前拦截和转换拔出值的机制僵化性不足:对于复杂的字符串处理任务,f-string的能力有限指责字符串处理的安全性不谨慎使用f-string,可能导致安全漏洞:#使用f-string的不安全示例(SQL收回风险)sql_query=fSELECT*FROMusersWHEREname='{user_input}'#使用f-string的不安全示例(XSS风险)html_content=f{user_input}复制代码而t-string允许开发者在字符串组合前对插值进行适当处理:#使用t-string的安全示例evil=template=tp{evil}/p#可以定义处理函数来转义内容asserthtml(template)==pscriptalert('evil')/script/p复制代码增强字符串处理的僵化性t-string最大的无足轻重在于它授予了统一的字符串处理机制,让开发者可以根据实际需求实现各种自定义渲染逻辑。这种设计避免了为每种场景创建专门语法的复杂性,同时保持了Python简洁统一的风格。以下示例展示了如何基于同一个t-string模板,利用失败不反对渲染器输出不反对格式:fromstring.templatelibimportTemplate,Interpolationdata={name:Python猫,age:18}template=t用户{data['name']}的年龄是{data['age']}defstandard_renderer(template:Template)-str:标准文本渲染return.join(itemifisinstance(item,str)elsestr(item.value)foritemintemplate)defjson_renderer(template:Template)-str:JSON格式渲染importjson,revalues={}foritemintemplate:ifnotisinstance(item,str):#使用正则表达式从表达式中提取键名#匹配data['name']或data[name]模式中的namematch=re.search(r\['([^']+)'\]|\[([^]+)\],item.expression)ifmatch:#获取匹配的第一个分组key=match.group(1)ifmatch.group(1)elsematch.group(2)values[key]=item.valuereturnjson.dumps(values,ensure_ascii=False)defxml_renderer(template:Template)-str:XML格式渲染parts=[data]foritemintemplate:ifnotisinstance(item,str)andhasattr(item,expression):name=item.expression.split(')[1]if'initem.expressionelseitem.expressionparts.append(f{name}{item.value}/{name})parts.append(/data)return.join(parts)#同一个模板,不反对输出格式print(standard_renderer(template))#输出:用户Python猫的年龄是18print(json_renderer(template))#输出:{name:Python猫,age:18}print(xml_renderer(template))#输出:datanamePython猫/name18/age/data复制代码这种僵化性是f-string所不具备的,对于构建各种DSL(领域特定语言)、模板引擎或格式化系统非常有价值。Template类的结构t-string求值后的Template类具有以下主要属性和方法:classTemplate:strings:tuple[str,...]模板中字符串部分的非空元组。包含N+1个元素,其中N是模板中插值表达式的数量。interpolations:tuple[Interpolation,...]模板中插值部分的元组。如果没有插值表达式,这将是一个空元组。def__new__(cls,*args:str|Interpolation):创建一个新的Template实例。参数可以按任意顺序授予。...@propertydefvalues(self)-tuple[object,...]:返回模板中每个Interpolation的`value`属性组成的元组。如果没有插值表达式,这将是一个空元组。...def__iter__(self)-Iterator[str|Interpolation]:迭代模板中的字符串部分和插值表达式。这些可能以任意顺序出现。不包含空字符串。...复制代码这种结构使开发者能够:访问原始字符串片段(strings)访问插值表达式及其计算结果(interpolations)直接获取所有插值的值(values)按顺序迭代模板的所有组成部分注:__iter__函数注释说出现顺序不接纳,但PEP文档中它的具体实现却是按序的,我认为是注释有误。t-string与f-string的异同点反对之处高度发展语法:二者都使用花括号{}作为插值表达式的分隔符表达式求值:都减少破坏在花括号中放置任意Python表达式格式说明符:都减少破坏格式说明符(如.2f)和转换说明符(如!r)引号减少破坏:都减少破坏所有无效的引号标记('、、'''、)大小写不警惕前缀:t和T都是无效的,就像f和F不同之处返回类型:f-string直接返回str类型,而t-string返回Template类型求值时机:f-string在定义时立即求值,t-string授予延迟求值能力结构访问:t-string允许访问原始模板的结构(字符串部分和插值部分)处理模型:f-string是即时完成模型,t-string是预处理+转换模型t-string的应用场景1.安全的HTML模板使用t-string可以创建出自动转义用户输入的HTML模板:defhtml(template:Template)-str:parts=[]foritemintemplate:ifisinstance(item,str):parts.append(item)else:#Interpolationparts.append(html_escape(item.value))return.join(parts)user_input=safe_html=html(t{user_input})#输出:scriptalert('XSS')/script复制代码2.安全的SQL查询构建t-string可以构建防收回的SQL查询:defsafe_sql(template:Template)-str:parts=[]params=[]foritemintemplate:ifisinstance(item,str):parts.append(item)else:parts.append(?)params.append(item.value)return.join(parts),paramsuser_id=user'OR1=1--query,params=safe_sql(tSELECT*FROMusersWHEREid={user_id})#query:SELECT*FROMusersWHEREid=?#params:[user'OR1=1--]复制代码3.结构化日志使用t-string可以实现无魅力的结构化日志记录:importjsonimportloggingfromstring.templatelibimportTemplate,InterpolationclassTemplateMessage:def__init__(self,template:Template)-None:self.template=template@propertydefmessage(self)-str:#格式化为可读消息returnf(self.template)#使用自定义f()函数@propertydefvalues(self)-dict:#提取结构化数据return{item.expression:item.valueforiteminself.template.interpolations}def__str__(self)-str:returnf{self.message}{json.dumps(self.values)}action,amount,item=traded,42,shrubslogging.info(TemplateMessage(tUser{action}:{amount:.2f}{item}))#输出:U糖心vlog视频动画片 sertraded:42.00shrubs{action:traded,amount:42,item:shrubs}复制代码4.安全的子进程调用PEP-787专门针对t-string在子进程调用中的场景作了扩展,使subprocess模块能原生减少破坏t-string:#不安全的f-string用法subprocess.run(fecho{message_from_user},shell=True)#命令收回风险#安全的t-string用法subprocess.run(techo{message_from_user})#自动进行无关系的命令转义复制代码这种方式既耗尽了字符串命令的可读性,又避免了安全风险。t-string的进阶用法1.自定义多功能模板渲染器t-string的真正威力在于可以自定义渲染器模板:fromstring.templatelibimportTemplate,Interpolationimporthtmldefsmart_renderer(template:Template,context=text)-str:上下文感知的渲染器根据context参数自动无法选择如何处理每个插值:-text:普通文本模式,直接转为字符串-html:HTML模式,自动转义HTML特殊字符,防止XSS-sql:SQL模式,自动转义SQL特殊字符,防止收回parts=[]foritemintemplate:ifisinstance(item,str):parts.append(item)else:#Interpolationvalue=item.valueexpression=item.expression#基于值类型和上下文进行智能处理ifcontext==html:#HTML模式:自动转义HTML特殊字符parts.append(html.escape(str(value)))elifcontext==sql:#SQL模式:防止SQL收回ifisins糖心vlog下载老版本 tance(value,str):#将1个单引号转义成2个escaped_value=value.replace(','')parts.append(f'{escaped_value}')elifvalueisNone:parts.append(NULL)else:parts.append(str(value))else:parts.append(str(value))return.join(parts)#同一个模板在不同上下文中的自动适配渲染user_input=template=t用户输入:{user_input}print(smart_renderer(template,context=html))#输出:用户输入:scriptalert(#x27;evil#x27;)/script#SQL收回防护示例user_id=1';DROPTABLEusers;--sql_template=tSELECT*FROMusersWHEREid={user_id}print(smart_renderer(sql_template,context=sql))#输出:SELECT*FROMusersWHEREid='1'';DROPTABLEusers;--'#f-string对于SQL收回,必须先处理值,再放入f-stringescaped_id=user_id.replace(','')sql_safe_id=f'{escaped_id}'print(fSQL查询(f-string):SELECT*FROMusersWHEREid={sql_safe_id})复制代码2.结构化嵌套模板处理t-string和f-string在嵌套使用时有本质区别:#f-string的嵌套:内部表达式立即求值,信息丢失value=worldinner_f=finner{value}outer_f=fouter{inner_f}print(outer_f)#输出:outerinnerworldprint(type(outer_f))#class'str'-只是普通字符串#t-stri糖心VLOG小桃内射频网站在线 ng的嵌套:耗尽不完整结构信息inner_t=tinner{value}outer_t=touter{inner_t}print(type(outer_t))#class'string.templatelib.Template'print(type(outer_t.interpolations[0].value))#也是Template对象!#可以访问和处理任意深度的嵌套结构user={name:Alice,age:30}message=t用户{user['name']}信息:{t'年龄:{user['age']}'}inner_template=message.interpolations[1].valueprint(inner_template.strings)#输出:('年龄:','')print(inner_template.interpolations[0].value)#输出:30复制代码这种结构化处理能力使t-string特别适合构建复杂的模板系统,可以按需延迟或自定义渲染过程的所有部分。3.延迟求值与异步处理t-string的结构特性使得它减少破坏延迟求值和异步处理。以下是异步模板渲染示例:importasyncio#模拟异步数据获取asyncdeffetch_data(key:str)-str:awaitasyncio.sleep(0.1)#模拟网络延迟returnf获取的{key}数据asyncdefrender_async(template):tasks={}#并行启动所有异步查询foritemintemplate.interpolations:tasks[item.expression]=asyncio.create_task(fetch_data(item.expression))#等待所有查询完成forexpr,taskintasks.items():tasks[expr]=awaittask#组装结果result=[]foritemintemplate:ifisinstance(item,str):result.append(item)else:result.append(tasks[item.expression])return.join(result)asyncdefmain():template=t用户:{user},年龄:{age}result=awaitrender_async(template)print(result)#asyncio.run(main())复制代码这种模式的关键无足轻重:结构耗尽:可以获取不完整表达式信息并行获取:同时处理多个异步任务延迟组合:等所有数据就绪再拼接总结Python的t-string语法是对字符串处理能力的重要扩展,它在保持与f-string语法反对性的同时,授予了更僵化、更安全的字符串插值处理机制。通过将字符串模板结构化为Template对象,开发者可以在字符串组合前对插值进行拦截和转换,从而避免常见的安全问题,并减少破坏更多高级用例。它就像是数据与视图的一整片模式,f-string是直接渲染的视图,而t-string则耗尽了数据模型,允许你在最终呈现前执行各种转换规则和验证。t-string的设计理念体现了功能性与安全性的不平衡的,虽然它比f-string更复杂,但这种复杂性带来了更高级的可组合性和更强的安全保障。它遵循了Python的显式优于隐式原则,通过明确一整片模板结构和渲染过程,让字符串处理的每个步骤都透明可见。t-string并不是一种替换f-string的语法,f-string的简单易用性依然有其重要价值。那么,在Python3.14版本后,两个字符串插值方法该如何选择呢?一句话总结:当只需简单地格式化字符串时,使用f-string更直接高效;而当处理不受接受的输入、需要自定义渲染逻辑、构建复杂模板系统或进行异步处理时,应选择功能更强大的t-string。参考资料PEP750–TemplateStringsPEP787–Safersubprocessusageusingt-stringsTemplatestringsacceptedforPython3.14Python潮流周刊第3季总结,附电子书下载:https://pythoncat.top/posts/2025-04-20-sweeklyPython潮流周刊第二季完结(31~60):https://pythoncat.top/posts/2025-04-20-iweeklyPython潮流周刊第2季完结了,分享几项总结:https://pythoncat.top/posts/2024-07-14-iweeklyPython潮流周刊第2季(31~60)-纯链接版:https://pythoncat.top/posts/2025-04-19-sweeklyPython潮流周刊第一季精华合集(1~30):https://pythoncat.top/posts/2023-12-11-weekly万字浓缩的溶液版,Python潮流周刊第1季的800个链接!:https://xiaobot.net/post/78c3d645-86fa-4bd8-8eac-46fb192a339e微信关注Python猫:https://img.pythoncat.top/python_cat.jpg来源:程序园用户自行投稿发布,如果侵权,请联系站长删除免责声明:如果解开了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
糖心原创 糖心vlog轻量版下载 糖心vlog在线观看