Forzar repr () para usar comillas simples

Tengo una pregunta, ¿hay una manera de “forzar” repr() para crear siempre comillas simples alrededor de una cadena?

Esto sucede cuando solo uso repr()

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

así que el último realmente lo hace, lo que quiero, pero no quiero agregar siempre \\" para obtener las comillas simples.


Edit: No voy a marcar una respuesta como aceptada ya que, como lo señaló @ martijn-pieters, estaba usando repr() para fines para los que no está destinado.

Bueno, si tu objeto es siempre una cadena, podrías hacer esto:

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

Pero como Martijn Pieters me preguntó, tengo curiosidad por su caso de uso aquí.

Necesitaba hacer algo similar una vez, excepto que siempre “prefería” usar comillas dobles, es decir, usarlas a menos que haya más de ellas en cadena que comillas simples (para minimizar el número de ellas que requerirían escapar) .

La forma en que hice esto fue subclasificar la clase str incorporada y anular su __repr__() . Probablemente podría revertir fácilmente la lógica de la misma para hacer lo contrario (además de forzar que el personaje que se usa para ser siempre uno u otro).

FWIW, aquí está el código:

 # -*- 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') 

Salida:

 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" 

Seguí adelante e implementé repr_double usando repr_double de stdout

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