Consider this class:
class foo(object): pass The default string representation looks something like this:
>>> str(foo) "<class '__main__.foo'>" How can I make this display a custom string?
5 Answers
Implement __str__() or __repr__() in the class's metaclass.
class MC(type): def __repr__(self): return 'Wahaha!' class C(object): __metaclass__ = MC print(C) Use __str__ if you mean a readable stringification, use __repr__ for unambiguous representations.
class foo(object): def __str__(self): return "representation" def __unicode__(self): return u"representation" 3If you have to choose between __repr__ or __str__ go for the first one, as by default implementation __str__ calls __repr__ when it wasn't defined.
Custom Vector3 example:
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 this example, repr returns again a string that can be directly consumed/executed, whereas str is more useful as a debug output.
v = Vector3([1,2,3]) print repr(v) #Vector3([1,2,3]) print str(v) #x:1, y:2, z:3 3Ignacio Vazquez-Abrams' approved answer is quite right. It is, however, from the Python 2 generation. An update for the now-current Python 3 would be:
class MC(type): def __repr__(self): return 'Wahaha!' class C(object, metaclass=MC): pass print(C) If you want code that runs across both Python 2 and Python 3, the six module has you covered:
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) Finally, if you have one class that you want to have a custom static repr, the class-based approach above works great. But if you have several, you'd have to generate a metaclass similar to MC for each, and that can get tiresome. In that case, taking your metaprogramming one step further and creating a metaclass factory makes things a bit cleaner:
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) prints:
Wahaha! Booyah! Gotcha! Metaprogramming isn't something you generally need everyday—but when you need it, it really hits the spot!
Just adding to all the fine answers, my version with decoration:
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! The down sides:
- You can't declare
Cwithout a super class (noclass C:) Cinstances will be instances of some strange derivation, so it's probably a good idea to add a__repr__for the instances as well.