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 Software Foundation が生の文字列リテラルを指定する方法をいつか変更したとしても、私のコードにはそれが反映されません。ただし、それは仮説です。私の主な関心事は、これが常に機能するかどうかです。ただし、頭のてっぺんからエッジケースを考えることはできません。これを行うより正式な方法はありますか?

編集: Format Specification Mini-Languageprintf-style String Formatting guide、またはstringmoduleには何も表示されないようです。

4

1 に答える 1

10

rawstring 表現の問題点は、移植可能な (つまり、制御文字を使用しない) 方法ですべてを表現できないことです。たとえば、文字列に改行がある場合、生の文字列として表すことができないため、文字通り文字列を次の行に分割する必要がありました。

そうは言っても、生文字列表現を取得する実際の方法は、あなたがすでに与えたものです:

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

生の文字列の定義は、最初の引用文字で終わることと、バックスラッシュを使用してその引用文字をエスケープできることを除いて適用されるルールがないことです。したがって、たとえば、"\"生の文字列表現 ( r"\"yields SyntaxError およびr"\\"yields "\\\\") のように、文字列に相当するものを格納することはできません。

本当にこれを行いたい場合は、次のようなラッパーを使用する必要があります。

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 に答える