[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