Force repr () use single quotes

My question is, is there a way to "force" to repr()

create always single quotes around a string?

This happens when I use repr()

print repr("test")
'test'
print repr("test'")
"test'"
print repr("test\"")
'test"'
print repr("test'\"")
'test\'"'

      

so the latter actually does what I want, but I don't want to add always \\"

to get single quotes.


Edit: I'm not going to mark the answer as accepted, since, as @ martijn-pieters pointed out, I used it repr()

for purposes it was not intended for.

+3


source to share


3 answers


Ok, if your object is always a string, you can do this:

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

print repr_single("test'")
'test\''

      



But since Martin Peters asked me, I am interested in your use case here.

+2


source


I needed to do something like this once, except that I wanted him to always "prefer" to use double quotes - that is, use them if there are more of them in the string than single quotes (to keep to a minimum the number of those that require shielding).

The way I did it is to subclass the built-in class str

and override its method __repr__()

. You could probably easily change the logic in it to do the opposite (and also force the character to always be this or that).

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"

      

+1


source


I went ahead and implemented repr_double

using stdoutrepr_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


source







All Articles