12

我正在制作一个严重依赖正则表达式的类。

假设我的班级看起来像这样:

class Example:
    def __init__(self, regex):
        self.regex = regex

    def __repr__(self):
        return 'Example({})'.format(repr(self.regex.pattern))

假设我这样使用它:

import re

example = Example(re.compile(r'\d+'))

如果我这样做repr(example),我得到'Example('\\\\d+')',但我想要'Example(r'\\d+')'。考虑到打印时正确显示的额外反斜杠。我想我可以实现它来 return "r'{}'".format(regex.pattern),但这对我来说并不合适。万一 Python 软件基金会有一天会改变指定原始字符串文字的方式,我的代码不会反映这一点。不过,这是假设的。我主要关心的是这是否总是有效。不过,我想不出一个边缘案例。有没有更正式的方式来做到这一点?

编辑: Format Specification Mini-Languageprintf-style String Formatting guidestringmodule中似乎没有出现任何内容。

4

1 回答 1

10

原始字符串表示的问题在于,您不能以可移植(即不使用控制字符)的方式表示所有内容。例如,如果您的字符串中有换行符,则必须将字符串从字面上断开到下一行,因为它不能表示为原始字符串。

也就是说,获取原始字符串表示的实际方法是您已经给出的:

"r'{}'".format(regex.pattern)

原始字符串的定义是没有应用任何规则,除了它们以它们开头的引号字符结束并且您可以使用反斜杠转义所述引号字符。因此,例如,您不能像"\"原始字符串表示形式那样存储字符串的等价物(r"\"yield SyntaxError 和r"\\"yield "\\\\")。

如果你真的想这样做,你应该使用像这样的包装器:

def rawstr(s):
    """
    Return the raw string representation (using r'') literals of the string
    *s* if it is available. If any invalid characters are encountered (or a
    string which cannot be represented as a rawstr), the default repr() result
    is returned.
    """
    if any(0 <= ord(ch) < 32 for ch in s):
        return repr(s)

    if (len(s) - len(s.rstrip("\\"))) % 2 == 1:
        return repr(s)

    pattern = "r'{0}'"
    if '"' in s:
        if "'" in s:
            return repr(s)
    elif "'" in s:
        pattern = 'r"{0}"'

    return pattern.format(s)

测试:

>>> test1 = "\\"
>>> test2 = "foobar \n"
>>> test3 = r"a \valid rawstring"
>>> test4 = "foo \\\\\\"
>>> test5 = r"foo \\"
>>> test6 = r"'"
>>> test7 = r'"'
>>> print(rawstr(test1))
'\\'
>>> print(rawstr(test2))
'foobar \n'
>>> print(rawstr(test3))
r'a \valid rawstring'
>>> print(rawstr(test4))
'foo \\\\\\'
>>> print(rawstr(test5))
r'foo \\'
>>> print(rawstr(test6))
r"'"
>>> print(rawstr(test7))
r'"'
于 2012-12-08T15:02:16.580 回答