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.

7
class foo(object): def __str__(self): return "representation" def __unicode__(self): return u"representation" 
3

If 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 
3

Ignacio 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:

  1. You can't declare C without a super class (no class C:)
  2. C instances will be instances of some strange derivation, so it's probably a good idea to add a __repr__ for the instances as well.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy