news 2026/4/16 17:01:08

Python PEP 822 提案:新增自动缩进移除的多行字符串语法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python PEP 822 提案:新增自动缩进移除的多行字符串语法

PEP 822 – 消除缩进的多行字符串(d-string)

作者:
Inada Naoki

摘要

本 PEP 提议增加一个功能,用于自动从多行字符串字面量中移除缩进。
消除缩进的多行字符串(dedented multiline strings)使用一个新的前缀“d”(“dedent”的简写),放在多行字符串字面量的开引号之前。
示例(空格用下划线_可视化):

defhello_paragraph()->str:____return d""" ________<p> __________Hello, World! ________</p> ____"""

末尾的三引号决定了要移除多少缩进。
在上面的例子中,返回的字符串将包含三行:

"____<p>\n"(四个前导空格)
"______Hello, World!\n"(六个前导空格)
"____</p>\n"(四个前导空格)

动机

在深度缩进的 Python 代码中编写多行字符串字面量时,用户面临以下选择:

  1. 接受字符串字面量的内容将左对齐。
  2. 使用多个单行字符串字面量拼接,而不是使用一个多行字符串字面量。
  3. 使用textwrap.dedent()来移除缩进。

所有这些选项在代码可读性和可维护性方面都有缺点。

  • 左对齐的多行字符串看起来不协调,往往被避免使用。在实践中,包括 Python 自己的测试代码在内的许多地方都选择其他方法。
  • 拼接的单行字符串字面量更冗长,更难维护。
  • textwrap.dedent()是用 Python 实现的,因此需要一些运行时开销。它不能在性能关键的热路径中使用。

本 PEP 旨在为消除缩进的多行字符串提供一种内置语法,它既易于读写,在运行时也高效。

原理

此想法的主要替代方案是用 C 语言实现textwrap.dedent()并将其作为str.dedent()方法提供。
这种方法可以减少textwrap.dedent()的运行时开销。通过使其成为内置方法,当直接在字符串字面量上调用时,还允许进行编译时缩进移除。
然而,这种方法有几个缺点:

  • 为了支持用户希望在字符串中包含某些缩进的情况,dedent()方法需要接受一个参数来指定要移除的缩进量。这对用户来说将是繁琐且容易出错的。
  • 当使用续行符(行尾带有反斜杠的行)时,它们无法被消除缩进。
  • f-字符串可能会将表达式插值为多行字符串而没有缩进。在这种情况下,f-string +str.dedent()无法消除整个字符串的缩进。
  • t-字符串不创建 str 对象,因此它们不能使用str.dedent()方法。虽然可以向string.templatelib.Template添加dedent()方法,但这会导致不一致,因为 t-字符串和 f-字符串非常相似,但在消除缩进方面会有不同的行为。

str.dedent()方法对于非字面量字符串仍然有用,因此本 PEP 并不排斥这个想法。
然而,为了便于在多行字符串字面量中使用,提供专用的语法更为优越。

规范

为消除缩进的多行字符串添加一个新的字符串字面量前缀“d”。
该前缀可以与“f”、“t”和“r”前缀组合使用。
该前缀仅用于多行字符串字面量。
因此,它只能与三引号("""''')一起使用。
在单引号或双引号("')上使用它是一个语法错误。
开头的三引号后必须跟一个换行符。此换行符不包含在结果字符串中。
要移除的缩进量由紧接在末尾三引号之前的空白字符(空格' '或制表符'\t')决定。
在缩进中混合使用空格和制表符会引发TabError,类似于 Python 自己的缩进规则。
消除缩进的过程从字符串中的每一行移除确定的先导空白字符量。
比确定的缩进量短的行会变成一个空行(例如"\n")。
否则,如果该行不是以确定的缩进开始,Python 会引发IndentationError
除非与“r”前缀结合使用,反斜杠转义在处理完移除缩进后才被处理。
因此,你不能使用\t来创建缩进。
并且你可以使用行延续符(行尾的反斜杠)并从延续行中移除缩进。

示例:
(为清晰起见,空格显示为_,制表符显示为--->。错误消息仅为解释,实际消息可能不同。)

s=d""# SyntaxError: d-string must be a multiline strings=d"""Hello"""# SyntaxError: d-string must be a multiline strings=d"""Hello __World! """# SyntaxError: d-string must start with a newlines=d""" __Hello __World!"""# SyntaxError: d-string must end with an indent-only lines=d""" __Hello __World! """# 不移除缩进,因为末尾引号没有缩进。print(repr(s))# '__Hello\n__World!\n's=d""" __Hello __World! _"""# 移除一个空格的缩进。print(repr(s))# '_Hello\n_World!\n's=d""" __Hello __World! __"""# 移除两个空格的缩进。print(repr(s))# 'Hello\nWorld!\n's=d""" __Hello __World! ___"""# IndentationError: missing valid indentations=d""" >--->__Hello >__World! >"""# 允许制表符作为缩进。# 空格只是字符串的一部分,不是要移除的缩进。print(repr(s))# '__Hello\n__World!\n's=d""" >____World! --->__"""# TabError: mixing spaces and tabs in indentations=d""" __Hello \ __World!\ __"""# 行延续符正常工作print(repr(s))# 'Hello_World!'s=d"""\ __Hello __World __"""# SyntaxError: d-string must starts with a newline.s=dr""" __Hello\ __World!\ __"""# d-string 可以与 r-string 结合。print(repr(s))# 'Hello\\\nWorld!\\\n's=df""" ____Hello,{"world".title()}! ____"""# d-string 也可以与 f-string 和 t-string 结合。print(repr(s))# 'Hello, World!\n's=dt""" ____Hello, {"world".title()}! ____"""print(type(s))# <class 'string.templatelib.Template'>print(s.strings)# ('Hello, ', '!\n')print(s.values)# ('World',)print(s.interpolations)# (Interpolation('World', '"world".title()', None, ''),)

如何教授此功能

在教程中,可以结合三引号字符串字面量来介绍 d-string。
此外,可以在textwrap.dedent()的文档中添加一个注释,提供指向语言参考中 d-string 部分或教程相关部分的链接。

其他具有类似功能的语言

  • Java 15引入了一个称为文本块(text blocks)的功能。由于 Java 以前没有使用三引号,他们引入了用于多行字符串字面量的三引号,并自动移除缩进。
  • C# 11也引入了一个类似的功能,称为原始字符串字面量(raw string literals)。
  • JuliaSwift也支持自动移除缩进的三引号字符串字面量。
  • PHP 7.3引入了灵活的 Heredoc 和 Nowdoc 语法。虽然它使用结束标记(例如<<<END ... END)而不是三引号,但它也会从文本中移除缩进。

Java 和 Julia 使用缩进最少的那一行来确定要移除的缩进量。
Swift、C# 和 PHP 使用末尾三引号或结束标记的缩进。
本 PEP 选择了 Swift 和 C# 的方法,因为它更简单且更容易解释。

参考实现

PEP 822 的一个 CPython 实现可在methane/cpython#108获取。

被拒绝的想法

str.dedent()方法

正如原理部分提到的,本 PEP 并不拒绝str.dedent()方法这个想法。
一个用 C 实现的更快的textwrap.dedent()版本对运行时缩进移除会很有用。
然而,d-string 更适合多行字符串字面量,因为:

  • 它能很好地与 f/t-strings 配合工作。
  • 它允许更轻松地指定要移除的缩进量。
  • 它可以消除续行符的缩进。

三重反引号(Triple-backtick)

考虑使用三重反引号作为消除缩进的多行字符串的替代语法。
这种符号在 Markdown 中为我们所熟悉。虽然过去存在对某些键盘布局的担忧,但如今许多人已经习惯输入这种符号。
然而,当在 Markdown 中嵌入 Python 代码或反之亦然时,这种符号会产生冲突。
因此,考虑到这些缺点,增加引号字符的种类被认为不如为字符串字面量添加前缀优越。

__future__导入

除了为字符串字面量添加前缀之外,还考虑过使用__future__导入来改变多行字符串字面量的默认行为。
这可能有助于将来简化 Python 的语法。
但是,将所有现有的复杂代码库重写为新符号可能并不简单。
在该源代码中的所有多行字符串都被重写为新符号之前,无法利用自动缩进移除功能。
在所有用户能够将现有代码库重写为新符号之前,两种类型的 Python 语法将无限期共存。
因此,许多人更喜欢新的字符串前缀,而不是__future__导入。

版权

本文档置于公共领域或 CC0-1.0-Universal 许可证下,以更宽松者为准。

来源:https://github.com/python/peps/blob/main/peps/pep-0822.rst
最后修改时间:2026-01-07 15:13:47 GMT
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)或者 我的个人博客 https://blog.qife122.com/
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 11:06:38

3D扫描数据全流程优化指南:从点云到打印模型的质量控制

3D扫描数据全流程优化指南&#xff1a;从点云到打印模型的质量控制 【免费下载链接】OrcaSlicer G-code generator for 3D printers (Bambu, Prusa, Voron, VzBot, RatRig, Creality, etc.) 项目地址: https://gitcode.com/GitHub_Trending/orc/OrcaSlicer 3D扫描技术已…

作者头像 李华
网站建设 2026/4/16 12:21:05

本体工程:企业AI Agent避免失败的语义层解决方案

文章阐述了企业AI Agent面临的语义理解困境&#xff0c;指出现有解决方案(Skills/RAG、Workflow)的局限性&#xff0c;提出引入本体(Ontology)作为企业AI的"语义层"。本体通过结构化表达业务概念、关系和规则&#xff0c;构建统一的业务知识理解&#xff0c;减少AI误…

作者头像 李华
网站建设 2026/4/16 12:20:58

深度解析Claude Code工具超时问题:从现象到实战的破局指南

深度解析Claude Code工具超时问题&#xff1a;从现象到实战的破局指南 【免费下载链接】claude-code Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining com…

作者头像 李华
网站建设 2026/4/16 14:13:23

RuoYi AI前端技术栈深度解析:Vben Admin与Naive UI架构实践

RuoYi AI前端技术栈深度解析&#xff1a;Vben Admin与Naive UI架构实践 【免费下载链接】ruoyi-ai 基于ruoyi-plus实现AI聊天和绘画功能-后端 本项目完全开源免费&#xff01; 后台管理界面使用elementUI服务端使用Java17SpringBoot3.X 项目地址: https://gitcode.com/GitHub…

作者头像 李华
网站建设 2026/4/16 11:07:18

go-cursor-help工具使用指南:解决Cursor试用限制的技术方案

go-cursor-help工具使用指南&#xff1a;解决Cursor试用限制的技术方案 【免费下载链接】go-cursor-help 解决Cursor在免费订阅期间出现以下提示的问题: Youve reached your trial request limit. / Too many free trial accounts used on this machine. Please upgrade to pro…

作者头像 李华