【问题标题】:How do I get the raw representation of a string in Python?如何在 Python 中获取字符串的原始表示?
【发布时间】:2012-11-26 13:05:20
【问题描述】:

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

假设我的班级是这样的:

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+')'。考虑到打印时正确显示的额外反斜杠。我想我可以实现它以返回"r'{}'".format(regex.pattern),但这并不适合我。万一 Python 软件基金会有一天会改变指定原始字符串文字的方式,我的代码不会反映这一点。不过,这是假设的。我主要关心的是这是否总是有效。不过,我想不出一个边缘案例。有更正式的方式吗?

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

【问题讨论】:

    标签: python python-3.x rawstring


    【解决方案1】:

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

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

    "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,没有捕获 all 字符串末尾奇数个反斜杠的实例),其余的都很丑陋( if any(&lt;condition involving c&gt; for c in s) 怎么样?)。
    • 好点,没有考虑反斜杠奇数的一般问题,我会尝试扩展它。
    • 刚刚玩完你的代码。这令人印象深刻!我什至没有考虑控制角色。我看到如果出现控制字符,您的函数会退回到正常的字符串表示形式。顺便说一句,filter 返回一个迭代器,所以不需要调用iter。 :) 谢谢。
    • @TylerCrompton 感谢您的感谢! filter:这取决于 python 版本。在 Python2 中,它将是一个列表。
    • @MarcH 这可能会隐藏一些东西,例如尝试打印string_var1 = "foo\rbar"。通常无关紧要,但在某些情况下可能(这就是存在诸如 repr() 之类的东西的原因)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 2014-08-21
    • 2019-08-17
    • 1970-01-01
    • 2015-04-03
    • 1970-01-01
    相关资源
    最近更新 更多