阅读reference manual,它在里面。
具体来说:
允许多个相邻的字符串或字节文字(由空格分隔),可能使用不同的引用约定,并且它们的含义与它们的连接相同。因此,"hello" 'world' 等价于 "helloworld"。 此功能可用于减少所需的反斜杠数量,方便地将长字符串拆分为长行,甚至可以将 cmets 添加到部分字符串中,
(强调我的)
这就是为什么:
string = str("Some chars "
"Some more chars")
与:str("Some chars Some more chars") 完全相同。
此操作在字符串文字可能出现的任何地方执行,列表初始化,函数调用(如上面的str 的情况)等等。
唯一需要注意的是,字符串文字不包含在grouping delimiters (), {} or [] 之一之间,而是在两个单独的physical lines 之间传播。在这种情况下,我们也可以将反斜杠字符 use 加入这些行并获得相同的结果:
string = "Some chars " \
"Some more chars"
当然,在同一物理行上串联字符串不需要反斜杠。 (string = "Hello " "World" 就好了)
Python 是加入这两个单独的字符串还是编辑器/编译器将它们视为单个字符串?
Python 是,现在什么时候 Python 确实做到了,这就是事情变得有趣的地方。
据我所知(请稍加注意,我不是解析专家),当 Python 转换解析树时会发生这种情况(LL(1) Parser em>) 将给定表达式与其对应的 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 和 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,而将解析树转换为抽象语法树的代码位于在Python/ast.c。
此信息适用于 Python 3.5,我很确定除非您使用一些非常旧的版本 (< 2.5),否则功能和位置应该相似。
此外,如果您对 python 的整个编译步骤感兴趣,核心贡献者之一 Brett Cannon 在视频中提供了一个很好的温和介绍 From Source to Code: How CPython's Compiler Works。