【问题标题】:Python Literal r'\' Not AcceptedPython 文字 r'\' 不被接受
【发布时间】:2012-04-17 02:44:57
【问题描述】:

r'\' 在 Python 中无法按预期工作。它不是返回一个包含一个字符(反斜杠)的字符串,而是引发一个 SyntaxError。 r"\" 也一样。

如果你有这样的 Windows 路径列表,这会相当麻烦:

paths = [ r'\bla\foo\bar',
          r'\bla\foo\bloh',
          r'\buff',
          r'\',
          # ...
        ]

这个文字不被接受有充分的理由吗?

【问题讨论】:

  • 实际上,在这样的文字中,作为最后一个字符的每个 \ 都会引发这个问题。
  • 使用/作为路径分隔符,或者在Windows中使用os.path.sep;也可以酌情使用os.path.split()os.path.join()
  • 改用u'\N{REVERSE SOLIDUS}foo\N{REVERSE SOLIDUS}bar'
  • @Alfe:也许更好的措辞是 Python 设计者认为您的用例不太可能并且不值得支持,并且更喜欢 LL(1) 解析器的简单性。 (有关解析器复杂性的简短评论,请参阅 PEP 3099。)这就是为什么这里的其他人都在回答“不要那样做”——你发现了一个小功能,旨在让某些模糊的边缘情况下的生活更轻松,而您之所以抱怨,是因为它不会让 您的 生活更轻松。软件工程中的一切都是一种权衡。
  • @Daniel:说得好!您能否提供一个参考,说明此“功能”需要更复杂的解析器?对我来说,为什么会这样并不是很明显。

标签: python syntax syntax-error literals


【解决方案1】:

反斜杠可用于使以下引号不终止字符串:

>>> r'\''
"\\'"

所以r'foo\'r'\' 是未终止的文字。

基本原理

由于您特别询问了此设计决策背后的原因,因此相关方面可能如下(当然这都是基于推测):

  • 简化 Python 解释器本身的词法分析(所有字符串文字都具有相同的语义:结束引号后不跟奇数个反斜杠终止字符串)
  • 简化语法高亮引擎的词法分析(这是一个强有力的论据,因为大多数编程语言没有原始字符串,仍然用单引号或双引号括起来,并且许多语法高亮引擎严重损坏因为他们使用不适当的工具(如正则表达式)进行词法分析)

所以是的,选择这种方式可能有重要的原因,即使您不同意这些原因,因为您认为您的特定用例更重要。然而事实并非如此,原因如下:

  • 您可以只使用普通字符串文字并转义反斜杠或从原始文件中读取字符串
  • 在以下两种情况之一中通常需要字符串文字中的反斜杠:
    • 您将字符串作为输入提供给另一种语言解释器,该解释器使用反斜杠作为引用字符,如正则表达式。在这种情况下,您将永远不需要在字符串末尾使用反斜杠
    • 您正在使用\ 作为路径分隔符,这通常不是必需的,因为Python 支持/ 作为Windows 上的路径分隔符,并且因为有os.path.sep

解决方案

您可以改用'\\'"\\"

>>> print("\\")
\

或者如果你完全疯了,你可以使用原始字符串文字并将它们与普通文字结合起来,只为结尾的反斜杠,甚至使用字符串切片:

>>> r'C:\some\long\freakin\file\path''\\'
'C:\\some\\long\\freakin\\file\\path\\'
>>> r'C:\some\long\freakin\file\path\ '[:-1]
'C:\\some\\long\\freakin\\file\\path\\'

或者,在您的特定情况下,您可以这样做:

paths = [ x.replace('/', '\\') for x in '''

  /bla/foo/bar
  /bla/foo/bloh
  /buff
  /

'''.strip().split()]

这会在添加更多路径时为您节省一些输入,作为额外的奖励。

【讨论】:

  • 我不是在寻找替代品,但还是谢谢你。我正在寻找这背后的基本原理的解释。
  • @Alfe:我一直在寻找这背后的理由,但在这样做之后,我认为除了简化解析并可能让语法荧光笔更容易获得它之外,没有什么其他的了正确的。所以简短的回答是:不,没有很好的理由不允许这样做。你投了反对票吗?如果是,为什么会这样?
  • 我的问题不是替代品,这就是我投反对票的原因。无意冒犯,但我的问题没有得到回答。
  • @Alfe:我们不能告诉你更多。您的问题不是很清楚,因为您无需使用原始字符串即可轻松实现您想要的。你的实际问题是什么? Python 设计者是这样决定的,这里提供的论点相当强大,您还期待什么?
  • @Alfe:这些设计决策比您的“用例”重要得多。你为什么不把这些字符串放到一个文件中或者只是转义反斜杠呢?这并不是说这会带来问题。请查看我的编辑。
【解决方案2】:

那是因为在原始字符串中,当字符串由单引号分隔时,您需要一种方法来转义单引号。与双引号相同。

http://docs.python.org/reference/lexical_analysis.html#string-literals

【讨论】:

  • 这意味着r'\'' 将与"'" 相同,但事实并非如此。
  • 实际上,r'\'' == "'" 的计算结果为 True
  • 不在 Python 2 和 Python 3 中?参考?
  • 命令行中的python解释器(在我的例子中是2.7)
  • 哎呀,对不起,我的错误,忘记了r前缀,呵呵
【解决方案3】:

这是按照documentation:

当存在'r''R' 前缀时,反斜杠后面的字符将原样包含在字符串中,并且所有反斜杠都保留在字符串中。例如,字符串文字 r"\n" 由两个字符组成:一个反斜杠和一个小写字母 'n'。字符串引号可以用反斜杠转义,但反斜杠保留在字符串中;例如,r"\"" 是由两个字符组成的有效字符串文字:反斜杠和双引号; r"\" 不是有效的字符串文字(即使是原始字符串也不能以奇数个反斜杠结尾)。具体来说,原始字符串不能以单个反斜杠结尾(因为反斜杠会转义后面的引号字符)。另请注意,后跟换行符的单个反斜杠被解释为这两个字符作为字符串的一部分,而不是作为续行符。

改用"\\",或者,甚至更好的是,使用/ 作为路径分隔符(是的,这适用于Windows)。

【讨论】:

  • “将转义以下引号字符”是什么意思?我所经历的行为似乎是反斜杠只会导致以下引号不终止字符串,但永远不会包含在文字中。你知道这背后的原因是什么吗?引用的文档似乎没有解释这一点(当然,尽管它以这种方式正确定义了它)。
  • @NiklasB.:“逃脱”的含义并不是特别明确。它的意思是“保留以下具有特殊含义的引号字符,同时在字符串中保留反斜杠”。我不确定这背后的理由。可能是不要过多地混淆编辑器中的语法突出显示,或者简化词法分析器。从用户的角度来看,我认为它没有用。
  • 谢谢,这与我的考虑一致
  • @Alfe:简化词法分析器并非没用。只需查看您自己帖子中的语法着色,即可了解以 \ 结尾的字符串文字的负面影响。这是一个设计决定,但如果没有进一步的了解,我不会说它不好。另一方面,在 DOS 和 Windows 中使用 \ 作为路径分隔符的决定 是一个糟糕的决定,至少事后看来是这样。幸运的是,您还可以在 Python 中使用/
  • 我只能在使用文件操作时使用 / 作为替换。就我而言,我只是在比较字符串:-/ 或::-\
【解决方案4】:

要解决您的根本问题,您可以使用 / 在 Python 中的 Windows 路径中就可以了

r''r"" 语法 (raw) 主要用于处理正则表达式。在使用您期望的路径的情况下,它并没有真正为您带来任何好处,尤其是在字符串以 \ 结尾的情况下。

否则如果你坚持使用\或者使用'\\'或者"\\",你必须转义转义字符\;这不漂亮,使用/os.path.sep 是最好的解决方案。

【讨论】:

  • 该死的编辑器正在逃避我的逃避,而不是显示我实际输入的内容!我没有输入@NiklasB 的内容。正在看。
  • 这些问题是 Markdown 的一个非常糟糕的领域:不兼容的实现。我已经使用双反引号而不是单反引号来修复它。
  • @NiklasB.: r'\\' 产生一个双反斜杠,'\\\\'
  • @Chris Morgan:我只是在这里引用答案(注意 not
  • 我的根本问题是无法使用 \ 作为原始字符串中的最后一个字符。 Windows 路径只是一个示例(实际上,我从文本文件中获取的字符串就是这样一个带有(有时)尾随反斜杠的路径,我想将其与我必须以某种方式表示的字符串进行比较,然后当然不应该用斜杠替换反斜杠;-)。
【解决方案5】:

对我的问题(“为什么不允许将反斜杠作为原始字符串中的最后一个字符?”)的答案实际上似乎是“这是一个设计决定”,而且是一个值得怀疑的问题。

一些答案​​试图推断词法分析器和一些语法荧光笔以这种方式更简单。我不同意(而且我有一些编写解析器和编译器以及 IDE 开发的背景)。使用反斜杠没有任何特殊含义的语义来定义原始字符串会更简单。词法分析器和 IDE 都将从这种简化中受益。

目前的情况也是wart:如果我想要原始字符串中的引号,无论如何我都不能使用它。如果我碰巧想要一个反斜杠,然后在我的原始字符串中加上一个引号,我只能使用它。

我会提议改变这一点,但我也看到了破坏现有代码的问题:-/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 2019-09-18
    相关资源
    最近更新 更多