Force repr() to use single quotes

前端 未结 3 608
孤独总比滥情好
孤独总比滥情好 2020-12-19 17:31

I have a question, is there a way to \"force\" repr() to create always single quotes around a string?

This happens when I only use repr()

相关标签:
3条回答
  • 2020-12-19 17:55

    I went ahead and implemented repr_double by using stdout's repr_single

    def repr_single(s):
        return "'" + repr('"' + s)[2:]
    
    def repr_double(s):
        single = repr_single(s)
        return '"' + single[1:-1].replace('"', '\\"').replace('\\\'', '\'') + '"'
    
    def test_single():
        assert r"'foobar'" == repr_single('foobar')
        assert r"'\'foobar'" == repr_single('\'foobar')
        assert "'\\'foobar'" == repr_single("'foobar")
    
    def test_double():
        assert r'"foobar"' == repr_double("foobar")
        assert '"\'foobar"' == repr_double("'foobar")
        assert '"\\"foobar"' == repr_double('"foobar')
    
    0 讨论(0)
  • 2020-12-19 18:00

    Well, if your object is always a string you could do this:

    def repr_single(s):
        return "'" + repr('"' + s)[2:]
    
    print repr_single("test'")
    'test\''
    

    But as Martijn Pieters asked I'm curious as to your use case here.

    0 讨论(0)
  • 2020-12-19 18:06

    I needed to do something similar once, except I wanted it to always "prefer" to use double quotes — meaning use them unless there were more of them in string than single quotes (in order to minimize the number of them that would require escaping).

    The way I did this was to subclass the built-in str class and override its __repr__() method. You could probably easily reverse the logic in it to do the opposite (as well as force the character used to always be one or the other).

    FWIW, here's the code:

    # -*- coding: iso-8859-1 -*-
    
    # Special string subclass to override the default
    # representation method. Main purpose is to
    # prefer using double quotes and avoid hex
    # representation on chars with an ord() > 128
    class MsgStr(str):
        def __repr__(self):
            # use double quotes unless there are more of them in the string than
            # single quotes
            quotechar = '"' if self.count("'") >= self.count('"') else "'"
            rep = [quotechar]
            for ch in self:
                # control char?
                if ord(ch) < ord(' '):
                    # remove the single quotes around the escaped representation
                    rep += repr(str(ch)).strip("'")
                # does embedded quote match quotechar being used?
                elif ch == quotechar:
                    rep += "\\"
                    rep += ch
                # else just use others as they are
                else:
                    rep += ch
            rep += quotechar
    
            return "".join(rep)
    
    if __name__ == "__main__":
        s1 = '\tWürttemberg'
        s2 = MsgStr(s1)
        print "str    s1:", s1
        print "MsgStr s2:", s2
        print "--only the next two should differ--"
        print "repr(s1):", repr(s1), "# uses built-in string 'repr'"
        print "repr(s2):", repr(s2), "# uses custom MsgStr 'repr'"
        print "str(s1):", str(s1)
        print "str(s2):", str(s2)
        print "repr(str(s1)):", repr(str(s1))
        print "repr(str(s2)):", repr(str(s2))
        print "MsgStr(repr(MsgStr('\tWürttemberg'))):", MsgStr(repr(MsgStr('\tWürttemberg')))
        assert eval(MsgStr(repr(MsgStr('\tWürttemberg')))) == MsgStr('\tWürttemberg')
    

    Output:

    str    s1:  Württemberg
    MsgStr s2:  Württemberg
    --only the next two should differ--
    repr(s1): '\tW\xfcrttemberg' # uses built-in string 'repr'
    repr(s2): "\tWürttemberg" # uses custom MsgStr 'repr'
    str(s1):    Württemberg
    str(s2):    Württemberg
    repr(str(s1)): '\tW\xfcrttemberg'
    repr(str(s2)): '\tW\xfcrttemberg'
    MsgStr(repr(MsgStr('    Württemberg'))): "\tWürttemberg"
    
    0 讨论(0)
提交回复
热议问题