Python字符串文字连接

Posted

技术标签:

【中文标题】Python字符串文字连接【英文标题】:Python string literal concatenation 【发布时间】:2016-03-14 11:22:37 【问题描述】:

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

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

这将产生以下字符串:

"Some chars Some more chars"

Python 是加入这两个单独的字符串还是编辑器/编译器将它们视为单个字符串?

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

【问题讨论】:

“python 是否正在加入这两个单独的字符串” - 是的,它确实如此。 This behaviour is even documented. 不过,它不是 multiline 字符串。此功能与换行无关。由于括号,Python 忽略了换行符。顺便说一句,可以使用三引号("""''')创建多行字符串。 【参考方案1】:

阅读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.pyLib/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

【讨论】:

感谢您的回答。这消除了我的疑问。另外我想问一下,当我说“一些字符”并且在下一行我说“更多字符”时,如果没有括在括号中,它不会产生相同的输出。所以,当他们说空格时,他们并不是指换行符,对吗? @falsetru 没有括号是行不通的。那只是满足python的占位符:) @GaneshSatpute,我的意思是只省略 str,而不是括号:("Some char " "Some more chars") @GaneshSatpute,您可以使用续行,只需在行尾添加"\"。那你就不需要括号了 @Jim 感谢您详尽的回答。我花了一段时间阅读和掌握。 :) 我可能也会去检查源代码。再次感谢您的投入

以上是关于Python字符串文字连接的主要内容,如果未能解决你的问题,请参考以下文章

python0.4----字符串

python 判断字符串中是否只有中文字符

在Python 3中删除字符串文字前面的'b'字符do [重复]

为啥 Python 的原始字符串文字不能以单个反斜杠结尾?

python:SyntaxError:EOL,同时扫描字符串文字

对 Python 返回 JSON 作为字符串而不是文字感到困惑