Considera questa classe:
class foo(object):
pass
La rappresentazione di stringa predefinita è simile alla seguente:
>>> str(foo)
"<class '__main__.foo'>"
Come posso rendere questo display una stringa personalizzata?
Considera questa classe:
class foo(object):
pass
La rappresentazione di stringa predefinita è simile alla seguente:
>>> str(foo)
"<class '__main__.foo'>"
Come posso rendere questo display una stringa personalizzata?
Risposte:
Implementa __str__()o __repr__()nella metaclasse della classe.
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object):
__metaclass__ = MC
print C
Utilizzare __str__se si intende una stringificazione leggibile, utilizzare __repr__per rappresentazioni non ambigue.
_representational corpo della classe e return self._representational __repr__()metodo della metaclasse.
__repr__per rappresentare C. Un'alternativa all'avere un _representationmembro è quella di creare una fabbrica di metaclasse che produca una metaclasse con il corretto __repr__(questo potrebbe essere utile se lo usi molto).
class foo(object):
def __str__(self):
return "representation"
def __unicode__(self):
return u"representation"
instancesla classe, non per la classe stessa.
Se devi scegliere tra __repr__o __str__scegliere il primo, come per impostazione predefinita, l'implementazione __str__chiama __repr__quando non è stato definito.
Esempio di Vector3 personalizzato:
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 questo esempio, reprrestituisce di nuovo una stringa che può essere consumata / eseguita direttamente, mentre strè più utile come output di debug.
v = Vector3([1,2,3])
print repr(v) #Vector3([1,2,3])
print str(v) #x:1, y:2, z:3
__repr__vs __str__è corretto, questo non risponde alla domanda reale, che riguarda gli oggetti di classe, non le istanze.
La risposta approvata da Ignacio Vazquez-Abrams è assolutamente corretta. È, tuttavia, dalla generazione di Python 2. Un aggiornamento per l'attuale Python 3 sarebbe:
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object, metaclass=MC):
pass
print(C)
Se si desidera che il codice venga eseguito su Python 2 e Python 3, il modulo sei è coperto:
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)
Infine, se si dispone di una classe per cui si desidera avere una repr statica personalizzata, l'approccio basato sulla classe sopra funziona alla grande. Ma se ne hai diversi, dovresti generare una metaclasse simile a MCciascuno di essi e questo può diventare noioso. In tal caso, fare un passo avanti con la metaprogrammazione e creare una fabbrica di metaclasse rende le cose un po 'più pulite:
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)
stampe:
Wahaha! Booyah! Gotcha!
La metaprogrammazione non è qualcosa di cui di solito hai bisogno ogni giorno, ma quando ne hai bisogno, colpisce davvero il punto!
Aggiungo solo a tutte le belle risposte, la mia versione con decorazioni:
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!
I lati negativi:
Csenza una super classe (no class C:)Cle istanze saranno istanze di una strana derivazione, quindi è probabilmente una buona idea aggiungere anche una __repr__per le istanze.