Python原始字符串和尾随反斜杠

38

曾经我遇到过一个问题,不知道它是Python的“bug”,还是至少算是一个缺陷。如果有人知道这种行为的任何理由,请告诉我。我刚刚在阅读《像Pythonista一样编码》时想起了它,这本书到目前为止非常有趣。我只熟悉Python 2.x系列。

原始字符串是以r为前缀的字符串。这非常好,因为我可以在正则表达式中使用反斜杠,而且我不需要每个地方都加倍。对于在Windows上编写一次性脚本也很方便,因此我也可以在那里使用反斜杠。(我知道我也可以使用正斜杠,但是一次性脚本通常包含从Windows中其他地方剪切和粘贴的内容。)

太好了!除非你真的想让你的字符串以反斜杠结尾。在'raw'字符串中没有办法做到这一点。

In [9]: r'\n'
Out[9]: '\\n'

In [10]: r'abc\n'
Out[10]: 'abc\\n'

In [11]: r'abc\'
------------------------------------------------
   File "<ipython console>", line 1
     r'abc\'
           ^
SyntaxError: EOL while scanning string literal


In [12]: r'abc\\'
Out[12]: 'abc\\\\'

在闭引号前加一个反斜杠是错误的,但两个反斜杠会给你两个反斜杠! 我肯定不是唯一一个被这个问题困扰的人吧?

对于为什么“原始”字符串中的反斜杠-引号不是原始的,您有什么想法吗?我的意思是,如果我想要嵌入单引号,我会在字符串周围使用双引号,反之亦然。 如果我两个都想要,我就用三个引号。 如果我真的想在原始字符串中连续使用三个引号,好吧,我想我只能自己处理了,但这被视为“正确的行为”吗?

这在Windows中的文件夹名称中尤其棘手,因为反斜杠是路径分隔符。

4个回答

24

这是一个常见问题解答

对于“你确实希望字符串以反斜杠结尾。在'raw'字符串中没有办法做到这一点。”的回复:该常见问题解答展示了如何解决此问题。

>>> r'ab\c' '\\' == 'ab\\c\\'
True
>>>

8
看起来确实是个设计缺陷。 - DS.
3
您建议的原始字符串的替代设计是什么? - John Machin
3
不知道这是常见问题解答,但或许应该假定它是。 ;) 我不代表@DS,但我的替代设计是“无转义处理”。你知道,就像罐子上写的那样? - dash-tom-bang
似乎这个FAQ的位置已经移动到了新的位置。如果我有足够的声望,我想我可以编辑你的答案,但我没有。 - oob
1
似乎Python解析原始字符串和普通字符串一样,然后“取消”转义?这是非常糟糕的行为。话虽如此,我认为这可以“修复”,而不会破坏任何现有的代码。 - GLRoman

4
原始字符串主要用于可读地编写正则表达式模式,这些模式从不需要尾随反斜杠。它们可能在 Windows 上会有用(在大多数情况下,您可以使用正斜杠 - Python 库接受任何一种形式!)。为了加强相关的意外,使包含单引号和双引号的正则表达式模式几乎不可能编写,这是不可接受的。

(“几乎”是因为三引号几乎总是有帮助的...但有时可能会有点麻烦)。

因此,是的,原始字符串被设计成以这种方式行事(禁止奇数个尾随反斜杠),并且当 Guido 发明它们时,它们被认为是完全符合“适当行为”的。


是的-我在我的原始帖子中解释了为什么我使用反斜杠。谢谢,我的意思正是三重引号可以解决在正则表达式中使用引号字符的任何问题。事实上,我想要一个尾随反斜杠,但从未使用过几种不同类型引号字符的正则表达式。 - dash-tom-bang
1
这仍然让我感到困惑,为什么会出现这种情况。所述原因是“这是同时拥有单引号和双引号的字符串的唯一方法”,这个理由不成立,因为您总是需要在必要的引号前面加上反斜杠,并且该反斜杠会保留在编译后的字符串中。我无法想象除了三引号之外如何创建仅包含单引号和双引号的字符串。 - dash-tom-bang
我希望我能给这个更多的赞。我认为这种行为非常不一致,但是这个答案提供了一些关于为什么这种行为非常不一致的提示。 - Dave C
1
等等,原始字符串处理是内置的,而正则表达式必须被导入 - 我不相信这个。Python 在这里失败了,修复将是最受欢迎的。 - GLRoman

3
另一种解决此问题的方法是:
 >>> print(r"Raw \with\ trailing backslash\ "[:-1])
 Raw \with\ trailing backslash\

已更新至Python 3,并删除了结尾的不必要斜杠,因为它暗示了一个转义符。

请注意,个人认为我不会使用上述方式。我想可能是因为这是一个具有更多内容而不仅仅是路径的大字符串。对于上述情况,我更喜欢非原始格式并加倍斜杠。


2
哦,太棒了,我们有一个“原始”字符串,在其中转义转义字符-这就是大多数人首先想要原始字符串的原因!Python在这里出现问题。 - GLRoman

-1
关于为什么“原始”字符串是“原始的,除了反斜杠引号”的想法?我的意思是,如果我想在其中嵌入单引号,我会在字符串周围使用双引号,反之亦然。
但这将引发一个问题,即为什么原始字符串是“原始的,除了嵌入的引号”?
你必须有一些转义机制,否则你根本无法在字符串内部使用外部引号字符。然后你需要一个转义机制来转义转义机制。

规则“你不能在字符串中使用周围的引号字符”似乎很容易遵循并且非常实用。在极为罕见的情况下,如果您需要单引号、双引号、三个单引号和三个双引号的全部四个,我认为这些不能全部出现在一个连续的原始字符串中是不太合适的。当我想要一个原始字符串时,我不想要转义字符,所以在原始字符串的一个位置有一个转义字符然后导致错误似乎很愚蠢。 - dash-tom-bang
@dash-tom-bang 这个规则完全禁止你使用那个字符。任何没有这种限制的规则都比有这种限制的规则更好。 - user207421
如果选择的话,你可能无法执行其他希望执行的操作(例如“有一个尾随反斜杠”),那么答案并不是那么绝对。 “这是原始字符串,除了…”违反了“做明显的事情”的愿望;应尽可能避免规则例外。 - dash-tom-bang
@dash-tom-bang 我也看不懂那个。 - user207421
@dash-tom-bang 在单引号字符串中,你可以在单引号之前使用它,就像你自己的例子一样。这几乎不需要进一步的经验证实。实际上,它甚至不值得进一步讨论。 - user207421
显示剩余4条评论

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