Considera esta clase:
class foo(object):
pass
La representación de cadena predeterminada se parece a esto:
>>> str(foo)
"<class '__main__.foo'>"
¿Cómo puedo hacer que esta pantalla sea una cadena personalizada?
Considera esta clase:
class foo(object):
pass
La representación de cadena predeterminada se parece a esto:
>>> str(foo)
"<class '__main__.foo'>"
¿Cómo puedo hacer que esta pantalla sea una cadena personalizada?
Respuestas:
Implementar __str__()
o __repr__()
en la metaclase de la clase.
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object):
__metaclass__ = MC
print C
Úselo __str__
si se refiere a una stringificación legible, úselo __repr__
para representaciones inequívocas.
_representation
al cuerpo de la clase y return self._representation
en el __repr__()
método de la metaclase.
__repr__
para representar C
. Una alternativa a tener un _representation
miembro es crear una fábrica de metaclases que produzca una metaclase con la adecuada __repr__
(esto podría ser bueno si está usando esto mucho).
class foo(object):
def __str__(self):
return "representation"
def __unicode__(self):
return u"representation"
instances
la clase, no para la clase en sí.
Si tiene que elegir __repr__
o elegir __str__
el primero, como por defecto __str__
llama a la implementación__repr__
cuando no se definió.
Ejemplo de 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)
En este ejemplo, repr
devuelve nuevamente una cadena que se puede consumir / ejecutar directamente, mientras que str
es más útil como salida de depuración.
v = Vector3([1,2,3])
print repr(v) #Vector3([1,2,3])
print str(v) #x:1, y:2, z:3
__repr__
vs __str__
es correcto, esto no responde a la pregunta real, que se trata de objetos de clase, no de instancias.
La respuesta aprobada de Ignacio Vázquez-Abrams es bastante correcta. Sin embargo, es de la generación Python 2. Una actualización para el actual Python 3 sería:
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object, metaclass=MC):
pass
print(C)
Si desea código que se ejecute tanto en Python 2 como en Python 3, el módulo seis lo tiene cubierto:
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)
Finalmente, si tiene una clase en la que desea tener una reproducción estática personalizada, el enfoque basado en la clase anterior funciona muy bien. Pero si tiene varios, tendría que generar una metaclase similar a la MC
de cada uno, y eso puede ser agotador. En ese caso, llevar su metaprogramación un paso más allá y crear una fábrica de metaclases hace las cosas un poco más limpias:
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)
huellas dactilares:
Wahaha! Booyah! Gotcha!
La metaprogramación no es algo que generalmente necesita todos los días, pero cuando lo necesita, ¡realmente da en el clavo!
Solo agregando a todas las buenas respuestas, mi versión con decoración:
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!
Los inconvenientes:
C
sin una superclase (no class C:
)C
las instancias serán instancias de alguna derivación extraña, por lo que probablemente sea una buena idea agregar también una __repr__
para las instancias.