Betrachten Sie diese Klasse:
class foo(object):
pass
Die Standarddarstellung der Zeichenfolge sieht ungefähr so aus:
>>> str(foo)
"<class '__main__.foo'>"
Wie kann ich diese Anzeige zu einer benutzerdefinierten Zeichenfolge machen?
Betrachten Sie diese Klasse:
class foo(object):
pass
Die Standarddarstellung der Zeichenfolge sieht ungefähr so aus:
>>> str(foo)
"<class '__main__.foo'>"
Wie kann ich diese Anzeige zu einer benutzerdefinierten Zeichenfolge machen?
Antworten:
Implementieren Sie __str__()oder __repr__()in der Metaklasse der Klasse.
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object):
__metaclass__ = MC
print C
Verwenden __str__Sie diese Option, wenn Sie eine lesbare Zeichenfolge meinen, __repr__für eindeutige Darstellungen.
_representationdem Klassenkörper und return self._representationder __repr__()Methode der Metaklasse eine Zeichenfolge hinzufügen .
__repr__für die Darstellung verwenden möchten C. Eine Alternative zu einem _representationMitglied besteht darin, eine Metaklassenfabrik zu erstellen, in der eine Metaklasse mit der richtigen Metaklasse erstellt wird __repr__(dies kann hilfreich sein, wenn Sie diese häufig verwenden).
class foo(object):
def __str__(self):
return "representation"
def __unicode__(self):
return u"representation"
instancesdie Klasse, nicht für die Klasse selbst.
Wenn Sie zwischen dem ersten wählen __repr__oder __str__sich für den ersten entscheiden müssen, wie dies standardmäßig der __str__Fall ist, __repr__wenn die Implementierung nicht definiert wurde.
Beispiel für einen benutzerdefinierten Vektor3:
class Vector3(object):
def __init__(self, args):
self.x = args[0]
self.y = args[1]
self.z = args[2]
def __repr__(self):
return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)
def __str__(self):
return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)
In diesem Beispiel wird reprerneut eine Zeichenfolge zurückgegeben, die direkt verwendet / ausgeführt werden kann, während strdies als Debug-Ausgabe nützlicher ist.
v = Vector3([1,2,3])
print repr(v) #Vector3([1,2,3])
print str(v) #x:1, y:2, z:3
__repr__vs __str__richtig ist, beantwortet dies nicht die eigentliche Frage, die sich auf Klassenobjekte und nicht auf Instanzen bezieht.
Die genehmigte Antwort von Ignacio Vazquez-Abrams ist völlig richtig. Es ist jedoch aus der Python 2-Generation. Ein Update für das jetzt aktuelle Python 3 wäre:
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object, metaclass=MC):
pass
print(C)
Wenn Sie Code wünschen, der sowohl in Python 2 als auch in Python 3 ausgeführt wird, haben Sie in den sechs Modulen Folgendes behandelt:
from __future__ import print_function
from six import with_metaclass
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(with_metaclass(MC)):
pass
print(C)
Wenn Sie eine Klasse haben, für die Sie einen benutzerdefinierten statischen Repräsentanten haben möchten, funktioniert der oben beschriebene klassenbasierte Ansatz hervorragend. Wenn Sie jedoch mehrere haben, müssen Sie MCfür jede eine ähnliche Metaklasse generieren , und das kann lästig werden. Wenn Sie in diesem Fall Ihre Metaprogrammierung noch einen Schritt weiter gehen und eine Metaklassenfabrik erstellen, werden die Dinge etwas sauberer:
from __future__ import print_function
from six import with_metaclass
def custom_class_repr(name):
"""
Factory that returns custom metaclass with a class ``__repr__`` that
returns ``name``.
"""
return type('whatever', (type,), {'__repr__': lambda self: name})
class C(with_metaclass(custom_class_repr('Wahaha!'))): pass
class D(with_metaclass(custom_class_repr('Booyah!'))): pass
class E(with_metaclass(custom_class_repr('Gotcha!'))): pass
print(C, D, E)
Drucke:
Wahaha! Booyah! Gotcha!
Metaprogrammierung ist nicht etwas, das Sie normalerweise jeden Tag brauchen - aber wenn Sie es brauchen, ist es genau das Richtige!
Ich füge nur all die schönen Antworten hinzu, meine Version mit Dekoration:
from __future__ import print_function
import six
def classrep(rep):
def decorate(cls):
class RepMetaclass(type):
def __repr__(self):
return rep
class Decorated(six.with_metaclass(RepMetaclass, cls)):
pass
return Decorated
return decorate
@classrep("Wahaha!")
class C(object):
pass
print(C)
stdout:
Wahaha!
Die Nachteile:
Cohne eine Superklasse deklarieren (nein class C:)CInstanzen sind Instanzen einer seltsamen Ableitung, daher ist es wahrscheinlich eine gute Idee, auch __repr__für die Instanzen eine hinzuzufügen .