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.
source to share
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"
source to share
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')
source to share