[Tutor] better way to make __repr__ methods for family of similar classes

Brian van den Broek broek at cc.umanitoba.ca
Wed Dec 14 01:33:34 CET 2005


Kent Johnson said unto the world upon 2005-12-13 16:34:
> Brian van den Broek wrote:
> 
>>Hi all,
>>
>>I think I must be doing something incorrectly. I have a family of 
>>classes that all have the same arguments to their __init__ methods.
>>
>>I want to give them all __repr__ methods. From the docs, this method 
>>should be written so that it looks like "a valid Python expression 
>>that could be used to recreate an object with the same value (given an 
>>appropriate environment)."
>>
>>What I have come up with is:
>>
>>class _A_Base(object):
>>     def __init__(self, arg1, arg2):
>>         # code here
>>     def __repr__(self):
>>         # str(self.__class__).split("'")[1] as
>>         # str(self.__class__) returns something of the form
>>         # <class 'module.classname'> and the split("'"[1] pulls
>>         # out module.classname
>>         return "%s%s" %(str(self.__class__).split("'")[1],
>>  		                    (self.arg1, self.arg2))
>>
>>class A1(_A_Base):
>>     def __init__(self, arg1, arg2):
>>         # code here
>>
>>etc.
>>
>>
>>This feels smelly and I think that the desire to give a family of 
>>similar classes __repr__ methods must be common enough that there will 
>>be a better way I am not thinking of.
> 
> 
> You can use self.__class__.__module__ and self.__class__.__name__ 
> instead of parsing str(self.__class__).

Hi Kent,

thanks! I knew there had to be an easier way that the manual parse. I 
tried to find it with dir(), but now I see this as odd:

 >>> class A(object):pass

 >>> a=A()
 >>> dir(a.__class__)
['__class__', '__delattr__', '__dict__', '__doc__', 
'__getattribute__', '__hash__', '__init__', '__module__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 
'__weakref__']
 >>> a.__class__.__name__
'A'
 >>>

So, a.__class__ has a __name__ attribute, but dir() doesn't know about 
it. Odd. Is there a reason for the dir-invisibility of the __name__ 
attribute that you know of?

I just checked, and the docs say that dir's returned list is "is not 
necessarily complete" <http://docs.python.org/lib/built-in-funcs.html>.
which I did not know.


> You could use a metaclass instead of a common base class. There are some 
> dubious advantages to this approach:
> - your classes don't have to inherit from a common base

In my case, I actually need a common base anyway, so this is no 
temptation. I can see how it would be if the classes didn't actually 
all have a conceptually common "is a" ancestor, though.

> - you can set the custom __repr__ for all classes in a module by 
> assigning __metaclass__ at the module (instead of class) level.
> 
> For example:
> 
> class AutoRepr(type):
>      def __init__(cls, name, bases, d):
>          super(type, cls).__init__(name, bases, d)
> 
>          def __repr__(self):
>              return '%s.%s(%s, %s)' % (cls.__module__, cls.__name__, 
> self.arg1, self.arg2)
> 
>          setattr(cls, '__repr__', __repr__)
> 
> __metaclass__ = AutoRepr # This makes AutoRepr be the meta class of A1
> 
> class A1:
>      def __init__(self, arg1, arg2):
>          self.arg1 = arg1
>          self.arg2 = arg2
> 
> a=A1(1, 2)
> 
> print repr(a)
> 
> 
> prints:
> __main__.A1(1, 2)


That's pretty cool! I think I'm going to have to try to unpack what's 
going on and then play with it to see if I can make it work with 
variable signatures, etc. Thanks for showing it.

Best,

Brian vdB



More information about the Tutor mailing list