python, x = """"""; 被解析为三重引号或三对引号
在Python中,你可以这样写:
x = """""" # x = ''
Python的词法分析器会把这个看作是两个空的三重引号吗?也就是说,像这样 x = """ """
(中间没有空格)?
这是我最初的想法。不过,在Python中,这种写法是可以的:
>>> "4" "5"
'45'
>>> # and
>>> "4""5"
'45'
所以我可以看到 x = """"""
可能也会被解析成 x = "" "" ""
(同样没有空格)。我只是想知道,""""""
是被解析成两个三重引号,还是三对普通引号?或者是完全不同的东西?谢谢!
补充:显然,作为一个Python程序员,这个问题并不重要。不过,Python解释器肯定要选择其中一种,我想知道它选择的是哪一种。
5 个回答
你可以使用 ast
模块来查看 Python 使用的语法树。例如:
>>> import ast
>>> source = '""""""""'
>>> node = ast.parse(source, mode='eval')
>>> ast.dump(node)
"Expression(body=Str(s=''))"
如你所见,它是一个空字符串。
如果你没有任何文本,那就没什么区别。试试下面的代码:
>>> """abc"""
'abc'
>>> "a""b""c"
'abc'
>>> "a""b""c" == """abc"""
True
这段话提到的是一对三重引号。
看看这个
>>> id("""""")
140579203310856
>>> id("")
140579203310856
>>> id("" "" "")
140579203310856
这基本上意味着,这对三重引号和普通的引号是一样的。
另外,如果你用两个双引号来做一个标识,如下所示
>>> id("""")
....
它不会结束,因为现在分析器把它当作文档字符串在处理,正在等待这个字符串正确结束。
从字面上看,它是一个单一的字符串。三重引号的字符串是唯一可以跨越多行的形式(和其他一些语言不同,其他语言可能允许所有字符串或没有字符串跨行)。
这种特定的语法可能是因为它让语法高亮变得简单,可以标记成对的引号。虽然这有时会错误地高亮无效的Python代码(比如单引号跨行的字符串),但对于文本编辑器来说,通常已经足够好了。
当解析器读取到一个引号时,它会检查是否有两个相同类型的引号,如果找到了,就会在连续的三个引号处结束这个字符串。否则,它会在下一个引号处结束字符串,除非前面有换行符,这种情况下就会报错。
你可以通过使用分词器来判断:
>>> from StringIO import StringIO
>>> from tokenize import generate_tokens as gt
>>> from pprint import pprint as pp
>>> code = 'x=""""""'
>>> codeio = StringIO(code)
>>> tokens = list(gt(codeio.readline))
>>> pp(tokens)
[(1, 'x', (1, 0), (1, 1), 'x=""""""'),
(51, '=', (1, 1), (1, 2), 'x=""""""'),
(3, '""""""', (1, 2), (1, 8), 'x=""""""'),
(0, '', (2, 0), (2, 0), '')]
第一个标记是'x',第二个是'=',第三个是'""""""'。并不是有三个'""'的标记。
附注:为了比较:
>>> othercode='y="led" "zeppelin"'
>>> othercodeio = StringIO(othercode)
>>> othertokens = list(gt(othercodeio.readline))
>>> pp(othertokens)
[(1, 'y', (1, 0), (1, 1), 'y="led" "zeppelin"'),
(51, '=', (1, 1), (1, 2), 'y="led" "zeppelin"'),
(3, '"led"', (1, 2), (1, 7), 'y="led" "zeppelin"'),
(3, '"zeppelin"', (1, 8), (1, 18), 'y="led" "zeppelin"'),
(0, '', (2, 0), (2, 0), '')]