5

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()

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

so the last one actually does, what I want, but I don't want to add always \\" to get the single quotes.


Edit: I am not going to mark an answer as accepted since, as pointed out by @martijn-pieters, I was using repr() for purposes it is not intended for.

Marcono1234
  • 5,856
  • 1
  • 25
  • 43
  • Maybe [this](https://docs.python.org/2/reference/datamodel.html#object.__repr__) will help you – Bhargav Rao Dec 10 '14 at 13:28
  • 12
    `repr()` is a **debugging tool**. Why are your requiring that it uses different quotes instead? You as a developer looking at the output can distinguish just fine between the quote types. So can Python when you paste back the result of a `repr(stringobject)` call; you can recreate the exact value that way. Those are the use-cases for `repr()`. But clearly you are using it for something else. That something is almost certainly best solved differently, *not* using `repr()`. – Martijn Pieters Dec 10 '14 at 13:30
  • I try to write a list in a file using `repr()` and then adding line breaks and tabs to format it in the textfile. At the end I want to have another function which uses `ast.iteral_eval()` to create out of the string from the file (with out the added line breaks and tabs) the list. – Marcono1234 Dec 11 '14 at 15:19
  • Related question, [Escape special characters in a Python string - Stack Overflow](https://stackoverflow.com/questions/4202538/escape-special-characters-in-a-python-string) – user202729 Dec 23 '22 at 08:41

3 Answers3

4

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.

stdout
  • 1,761
  • 1
  • 18
  • 33
  • That looks pretty good, however I noticed I do not necessarily need `repr()`. My goal was to escape a string with all its special characters – Marcono1234 Jul 17 '15 at 15:48
2

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"
martineau
  • 119,623
  • 25
  • 170
  • 301
  • I solved the problem in a different way because I noticed that I only need to escape some characters, but thank you anyways – Marcono1234 Jul 17 '15 at 15:46
0

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')
vitiral
  • 8,446
  • 8
  • 29
  • 43