Using class attributes

Terry Reedy tjreedy at udel.edu
Tue Feb 16 17:59:59 CET 2010


On 2/16/2010 8:56 AM, Leo Breebaart wrote:
> Chris Rebert<clp2 at rebertia.com>  writes:
>
>> On Mon, Feb 15, 2010 at 10:29 AM, Leo Breebaart<leo at lspace.org>  wrote:
>>
>>> I have a base class Foo with a number of derived classes FooA,
>>> FooB, FooC, etc. Each of these derived classes needs to read
>>> (upon initialisation) text from an associated template file
>>> FooA.tmpl, FooB.tmpl, FooC.tmpl, etc.
>>> [...]
>>> But, since this information is the same for every instance of
>>> each derived class, I was wondering if there was a way to achieve
>>> the same thing outside of the __init__ function, and just have
>>> these assignments be done as a class attribute (i.e. so that I
>>> can refer to FooA.template_body, etc.)
>>
>> Metaclasses to the rescue!:
>>
>> class WithTemplateAttrs(type):
>>      def __new__(cls, name, bases, dct):
>>          klass =3D type.__new__(cls, name, bases, dct)
>>          klass.template_filename =3D "%s.tmpl" % name
>>          klass.template_body =3D read_body_from(klass.template_filename)
>>          return klass
>>
>> class Foo(object):
>>      __metaclass__ =3D WithTemplateAttrs
>>      #rest of class body here
>>
>> Now just have FooA, FooB, etc. subclass Foo as before. They'll
>> automatically get the attributes generated.
>
> Thanks for the feedback! I am thrilled that an actual real-life
> issue I'm having may be resolvable by metaclasses (which so far
> I've only admired from afar but never considered relevant to my
> day-to-day work),

I thought this a really nice example of metaclass use too.

 > but unfortunately I'm still struggling to get
> this to work.
>
> If I add your code, what happens is that the Foo class will try
> to read "Foo.tmpl", which does not exist -- it is only the
> derived classes FooA etc, that need to execute this code, not Foo
> itself.

My simpleminded solution to the above would be to create a dummy 
Foo.tmpl file, so it does exist. Or, in __new__ above, conditionalize 
the fetch: if name != 'Foo': ...

Terry Jan Reedy




More information about the Python-list mailing list