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.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。
【讨论】:
感谢您的回答。这消除了我的疑问。另外我想问一下,当我说“一些字符”并且在下一行我说“更多字符”时,如果没有括在括号中,它不会产生相同的输出。所以,当他们说空格时,他们并不是指换行符,对吗? @falsetru 没有括号是行不通的。那只是满足python的占位符:) @GaneshSatpute,我的意思是只省略str
,而不是括号:("Some char " "Some more chars")
@GaneshSatpute,您可以使用续行,只需在行尾添加"\"
。那你就不需要括号了
@Jim 感谢您详尽的回答。我花了一段时间阅读和掌握。 :) 我可能也会去检查源代码。再次感谢您的投入以上是关于Python字符串文字连接的主要内容,如果未能解决你的问题,请参考以下文章
在Python 3中删除字符串文字前面的'b'字符do [重复]