Considere esta classe:
class foo(object):
pass
A representação de string padrão é algo como isto:
>>> str(foo)
"<class '__main__.foo'>"
Como faço para exibir essa string personalizada?
Considere esta classe:
class foo(object):
pass
A representação de string padrão é algo como isto:
>>> str(foo)
"<class '__main__.foo'>"
Como faço para exibir essa string personalizada?
Respostas:
Implemente __str__()
ou __repr__()
na metaclasse da classe.
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object):
__metaclass__ = MC
print C
Use __str__
se você quer dizer uma stringificação legível, use __repr__
para representações inequívocas.
_representation
no corpo da classe e return self._representation
no __repr__()
método da metaclasse.
__repr__
para representar C
. Uma alternativa para ter um _representation
membro é criar uma fábrica de metaclasse que produza uma metaclasse com o apropriado __repr__
(isso pode ser bom se você estiver usando muito isso).
class foo(object):
def __str__(self):
return "representation"
def __unicode__(self):
return u"representation"
instances
a classe, não para a própria classe.
Se você precisar escolher __repr__
ou __str__
optar pelo primeiro, como a implementação padrão __str__
chama __repr__
quando não foi definido.
Exemplo Vector3 personalizado:
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)
Neste exemplo, repr
retorna novamente uma sequência que pode ser consumida / executada diretamente, enquanto str
é mais útil como uma saída de depuração.
v = Vector3([1,2,3])
print repr(v) #Vector3([1,2,3])
print str(v) #x:1, y:2, z:3
__repr__
vs __str__
esteja correto, isso não responde à pergunta real, que é sobre objetos de classe, não instâncias.
A resposta aprovada de Ignacio Vazquez-Abrams está certa. É, no entanto, da geração Python 2. Uma atualização para o Python 3 agora atual seria:
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object, metaclass=MC):
pass
print(C)
Se você deseja que o código seja executado tanto no Python 2 quanto no Python 3, o módulo seis foi coberto:
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)
Por fim, se você tem uma classe que deseja ter uma repr estática personalizada, a abordagem baseada em classe acima funciona muito bem. Mas se você tiver vários, terá que gerar uma metaclasse semelhante a MC
cada um, e isso pode ser cansativo. Nesse caso, levar sua metaprogramação um passo adiante e criar uma fábrica de metaclasses torna as coisas um pouco mais limpas:
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)
impressões:
Wahaha! Booyah! Gotcha!
A metaprogramação não é algo que você geralmente precisa todos os dias - mas quando você precisa, realmente atinge o ponto!
Apenas adicionando a todas as boas respostas, minha versão com decoração:
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!
Os lados inferiores:
C
sem uma super classe (não class C:
)C
instâncias serão instâncias de alguma derivação estranha; portanto, provavelmente é uma boa ideia adicionar um __repr__
para as instâncias também.