Python 字符串文字连接

Python string literal concatenation

我可以使用以下语法创建多行字符串:

string = str("Some chars "
         "Some more chars")

这将产生以下字符串:

"Some chars Some more chars"

是 Python 连接这两个单独的字符串还是 editor/compiler 将它们视为一个字符串?

P.s:我只是想了解一下内部结构。我知道还有其他方法可以声明或创建多行字符串。

阅读reference manual它就在那里。 具体来说:

Multiple adjacent string or bytes literals (delimited by whitespace), possibly using different quoting conventions, are allowed, and their meaning is the same as their concatenation. Thus, "hello" 'world' is equivalent to "helloworld". This feature can be used to reduce the number of backslashes needed, to split long strings conveniently across long lines, or even to add comments to parts of strings,

(强调我的)

这就是为什么:

string = str("Some chars "
         "Some more chars")

str("Some chars Some more chars").

完全相同

此操作在可能出现字符串文字、列表初始化、函数调用(如上面 str 的情况)等的任何地方执行。

唯一需要注意的是,当字符串文字 包含在 grouping delimiters (), {} or [] but, instead, spreads between two separate physical lines. In that case we can alternatively use 反斜杠字符之一之间时,连接这些行并获得相同的结果:

string = "Some chars " \
         "Some more chars"

当然,在同一物理行上串联字符串不需要反斜杠。 (string = "Hello " "World"就好了)


Is Python joining these two separate strings or is the editor/compiler treating them as a single string?

Python 是,现在 确实 Python 做到了,这就是事情变得有趣的地方。

据我所知(对此持保留态度,我不是解析专家),当 Python 转换解析树时会发生这种情况(LL(1) Parser) for a given expression to it's corresponding AST (Abstract Syntax Tree)

您可以通过 parser 模块查看已解析的树:

import parser

expr = """
       str("Hello "
           "World")
"""
pexpr = parser.expr(expr)
parser.st2list(pexpr)

这会转储一个相当大且令人困惑的列表,该列表表示从 expr 中的表达式解析的具体语法树:

-- rest snipped for brevity --

          [322,
             [323,
                [3, '"hello"'],
                [3, '"world"']]]]]]]]]]]]]]]]]],

-- rest snipped for brevity --

这些数字对应于解析树中的符号或标记,并且从符号到语法规则和标记到常量的映射分别在Lib/symbol.py and Lib/token.py中。

正如您在我添加的截取版本中看到的那样,您有两个不同的条目对应于已解析表达式中的两个不同 str 文字。

接下来,我们可以通过标准库中提供的ast模块查看前面表达式产生的AST树的输出:

p = ast.parse(expr)
ast.dump(p)

# this prints out the following:
"Module(body = [Expr(value = Call(func = Name(id = 'str', ctx = Load()), args = [Str(s = 'hello world')], keywords = []))])"

这种情况下的输出对用户更友好;您可以看到函数调用的 args 是单个连接字符串 Hello World.

此外,我还偶然发现了一个很酷的 module,它可以为 ast 个节点生成树的可视化。使用它,表达式 expr 的输出可视化如下:

图像被裁剪以仅显示表达式的相关部分。

如您所见,在终端叶节点中我们有一个 str 对象,即 "Hello ""World" 的连接字符串,即 "Hello World"


如果你够勇敢,请深入研究源代码,将表达式转换为解析树的源代码位于Parser/pgen.c while the code transforming the parse tree into an Abstract Syntax Tree is in Python/ast.c.

此信息适用于 Python 3.5,我很确定除非您使用某些 非常旧的 版本 (< 2.5),否则功能和位置应该相似。

此外,如果您对 python 之后的整个编译步骤感兴趣,核心贡献者之一 Brett Cannon 在视频 [=51] 中提供了一个很好的温和介绍=].