Beste Ausgangstyp und Codierungspraktiken für __Rep __ () Funktionen?
Frage
In letzter Zeit hatte ich viel Probleme mit __repr__()
, format()
, und Codings. Sollte die Ausgabe von __repr__()
codiert werden oder eine Unicode -Zeichenfolge sein? Gibt es eine beste Codierung für das Ergebnis von __repr__()
in Python? Was ich ausgeben möchte, hat keine ASCII-Zeichen.
Ich verwende Python 2.x und möchte Code schreiben, der leicht an Python 3. Das Programm verwendet
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function # The 'Hello' literal represents a Unicode object
Hier sind einige zusätzliche Probleme, die mich gestört haben, und ich suche eine Lösung, die sie löst:
- Das Drucken eines UTF-8-Terminals sollte funktionieren (ich habe
sys.stdout.encoding
einstellenUTF-8
, aber es wäre am besten, wenn auch andere Fälle funktionieren). - Die Ausgabe in eine Datei (in UTF-8 codiert) sollte funktionieren (in diesem Fall,
sys.stdout.encoding
istNone
). - Mein Code für viele
__repr__()
Funktionen haben derzeit vielereturn ….encode('utf-8')
, und das ist schwer. Gibt es etwas Robustes und Leichteres? - In einigen Fällen habe ich sogar hässliche Bestien wie
return ('<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')
, dh die Darstellung von Objekten ist dekodiert, in eine formatierende Zeichenfolge eingebaut und dann neu eingestuft. Ich möchte solche verschlungenen Transformationen vermeiden.
Was würden Sie empfehlen, um einfach zu schreiben? __repr__()
Funktionen, die sich in Bezug auf diese Codierungsfragen gut verhalten?
Lösung
In Python2, __repr__
(und __str__
) muss ein String -Objekt zurückgeben, kein Unicode -Objekt. In Python3 ist die Situation umgekehrt, __repr__
und __str__
Muss Unicode -Objekte zurückgeben, nicht Byte (nee String) -Objekte:
class Foo(object):
def __repr__(self):
return u'\N{WHITE SMILING FACE}'
class Bar(object):
def __repr__(self):
return u'\N{WHITE SMILING FACE}'.encode('utf8')
repr(Bar())
# ☺
repr(Foo())
# UnicodeEncodeError: 'ascii' codec can't encode character u'\u263a' in position 0: ordinal not in range(128)
In Python2 haben Sie keine Wahl. Sie müssen eine Codierung für den Rückgabewert von auswählen __repr__
.
Haben Sie übrigens die gelesen Printfails wiki? Es kann Ihre anderen Fragen möglicherweise nicht direkt beantworten, aber ich fand es hilfreich, um zu beleuchten, warum bestimmte Fehler auftreten.
Beim Benutzen from __future__ import unicode_literals
,
'<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')
kann einfacher geschrieben werden als
str('<{}>').format(repr(x))
Annahme str
kodiert zu utf-8
auf Ihrem System.
Ohne from __future__ import unicode_literals
, Der Ausdruck kann geschrieben werden als:
'<{}>'.format(repr(x))
Andere Tipps
Ich denke, ein Dekorateur kann es schaffen __repr__
Inkompatibilitäten auf vernünftige Weise. Hier ist, was ich benutze:
from __future__ import unicode_literals, print_function
import sys
def force_encoded_string_output(func):
if sys.version_info.major < 3:
def _func(*args, **kwargs):
return func(*args, **kwargs).encode(sys.stdout.encoding or 'utf-8')
return _func
else:
return func
class MyDummyClass(object):
@force_encoded_string_output
def __repr__(self):
return 'My Dummy Class! \N{WHITE SMILING FACE}'
Ich benutze eine Funktion wie Folgendes:
def stdout_encode(u, default='UTF8'):
if sys.stdout.encoding:
return u.encode(sys.stdout.encoding)
return u.encode(default)
Dann meine __repr__
Funktionen sehen so aus:
def __repr__(self):
return stdout_encode(u'<MyClass {0} {1}>'.format(self.abcd, self.efgh))