如何在Python中获取字符串的原始表示?

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+'))

如果我对example使用repr(),会得到'Example('\\\\d+')',但我想要'Example(r'\\d+')',注意在打印时出现了额外的反斜杠,看起来是正确的。我想我可以实现"r'{}'".format(regex.pattern)来返回正确的结果,但这让我感到不舒服。万一Python软件基金会有一天改变了原始字符串字面量的指定方式,我的代码就不能反映出来了。尽管如此,我的主要关注点是它是否总是有效的。虽然我目前想不到任何特殊情况。有没有更正式的方法来做到这一点?

编辑:在格式规范迷你语言printf-样式字符串格式化指南string模块中似乎都没有相关内容。

1个回答

11

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

话虽如此,获取原始字符串表示的实际方法就是您已经给出的:

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

原始字符串的定义是除了以引号开始和结束外,没有其他规则适用,你可以使用反斜杠来转义该引号字符。因此,例如,您不能将像"\"这样的字符串存储为原始字符串表示形式(r"\"会产生SyntaxError,r"\\"会产生"\\\\")。

如果您真的想这样做,可以使用类似以下的包装器:

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'"'

1
虽然实现有缺陷(假定ASCII,不能捕获字符串末尾所有奇数个反斜杠的情况),而且其余部分也很丑陋(怎么样使用 if any(<condition involving c> for c in s)?),但是还是要点赞。 - user395760
这里有一个问题:如果字符串包含 ' 字符,它将无法工作。 - interjay
这个复杂的答案间接地教会我一个更简单的课程。当我在交互式Python环境或调试器中想要查看一个字符串变量时,我不再只是输入它的名称了。相反,我使用print(string_var1) - MarcH
1
@MarcH 这可能会隐藏一些东西,请尝试打印“string_var1 =“foo \ rbar””。通常不会有影响,但在某些情况下可能会有影响(这就是为什么存在repr()之类的东西)。 - Jonas Schäfer
感谢 @JonasSchäfer,你是对的:对于棘手的字符串问题,你需要在调试器中同时使用string_var1print(string_var1)。但如果只是简单地计算反斜杠数量,print(string_var1)就足够了 :-) - MarcH
显示剩余10条评论

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