为什么Python在字符串引号不匹配时不会报错?

68

我最近开始学习Python,但我不明白为什么Python会像这样表现:

>>> "OK"
'OK'
>>> """OK"""
'OK'
>>> "not Ok'
  File "<stdin>", line 1
    "not Ok'
           ^
SyntaxError: EOL while scanning string literal
>>> "not OK"""
'not OK'

为什么最后一条语句没有报错?因为引号的数量不匹配。


8
如果您需要正式的文档,请点击这里 - Karl Knechtel
2
只是提供更多的见解:我认为让你困惑的是你将 """OK""" 解释为一个 "引号内嵌套引号" 的 "("("OK")")",但实际上不是这样的。三重引号 ("""'''),虽然由三个字符组成,但被视为一个单独的符号,用于开始(和结束)一个多行的原样字符串(参见这里)。你不能真正地嵌套引号;在像 "foo 'bar'"'foo "bar"' 这样的东西中,内部引号被视为普通字符,所以这也可以工作 "foo ' bar" - Filip Milovanović
4个回答

112

最终的"""不被识别为三引号,而是一个单个的"(用于关闭当前的字符串字面量),后跟一个空字符串"";两个并置的字符串字面量将被连接。通过在关闭和打开"之间放置一个空格,可以更容易地识别相同的行为。

>>> "not OK" ""
'not OK'

16
为了更好地说明这一点:>>>"ok"''>>>'ok'"" - DukeSilver
9
附注:@DukeSilver 不要认为在评论中像在问题和答案中一样在代码片段前面加上 >>> 会起到同样的作用。对于一些人来说,这可能看起来像是你在使用奇怪的外星操作符,而 "ok"'' 则是完全可读的。 提示:在评论中使用 >>> 来引用代码片段可能不如在问题和答案中有效。对于一些人来说,这可能看起来像是一个奇怪的外星运算符,而 "ok"'' 更容易理解。请注意保持原意并使语言更通俗易懂。 - Paul Evans
@PaulEvans 这是 Python 控制台在您输入的每一行前面放置的标记。 - nick012000
8
我知道,这就是为什么在问题和答案中它能够很好地工作。我的观点是,在评论中使用这个可能是不必要的,也可能会造成混淆。 - Paul Evans

32

"not OK"""

Python 解释为 "not OK"+""

如果你输入 "not Ok""ay",将会得到输出结果为 'not Okay'


1
"ok"无效语法。是不是应该写成"""ok"""?它给我一些奇怪的东西。 - ibra
3
在Python中,如果需要创建多行字符串,就可以使用三引号 """。当Python遇到三引号时,它会寻找开始三引号的结束三引号,以此来构建多行字符串。请注意,不要改变原文意思。 - Sandrin Joy
9
Python在寻找字符串的开始引号时,会优先选择三重引号而不是普通引号。但一旦确定了开始引号,结束引号也就确定了;因此,如果字符串以普通双引号开头,则另一端只使用一个双引号,并且其后的任何内容都是下一个标记的一部分。 - Karl Knechtel

9
你可能认为在使用 " 或 ' 方面没有区别,但实际上,Python使用贪婪方法接受输入。一旦Python看到匹配的引号,那么该语句就终止了。这就是为什么你可以写像 "'s""" 这样的东西。字符串中有一个 ',但因为你在一个字符串中,Python不会报错。然后,在此之后,有一个 ",跟随着另一个(空)字符串。"s' 这样的操作,Python会在运行命令之前查找下一个 "

5
为什么你把这个方法称为“贪心算法”? - Stef
3
因为这是一类算法的通用描述,它们会选择“第一个合适”的选项,即使后面的选项更好。 - Ingix
10
“贪婪”并不是指“贪心”。在正则表达式中,“贪婪”表示当你使用类似于A.*B的正则表达式匹配一个字符串时,它会匹配像ABBB这样的字符串,而不仅仅是AB,因为该正则表达式是“贪婪”的。 - user
4
支持上面Pat-Laugh的观点:实际上这与“贪心算法”完全相反,这是一种懒惰算法 - Will
它并不完全是懒惰的,但 """ 开始引用是贪婪的。(虽然大多数东西都是懒惰的。) - wizzwizz4

-3

Python使用类似于栈的实现来检测引号的开启和关闭。 如果你知道什么是栈,它是一种数据结构,其中最后一个元素将首先被移除。

假设你的字符串是A = "''" 它的作用是,对于每个第一次遇到的单引号或双引号,它将其添加到堆栈中,对于每个第二个,则将其从堆栈中移除,除非当然是""",这将被解析为单个引号

在我们的例子中,A = "''",迭代它,对于前两个元素,它们将被添加到堆栈中,对于接下来的两个元素,它们将被移除。

因此,只有在结束时堆栈中的元素数量为零时,引号才会匹配。


3
如果该字符串是"'",它不会被允许,因为在解析整个字符串后堆栈不为空?这是不正确的。 - Asocia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接