Using class attributes

Leo Breebaart leo at lspace.org
Tue Feb 16 08:56:45 EST 2010


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), 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.

And actually that makes sense -- I think my problem was not too
clearly thought out to begin with. Of course it's not possible to
associate a single template_body with the Foo class, it will be a
different template for each derived class. So at best I need to
associate your metaclass with each derived class, but at that
point I might as well just read the template in the __init__()
method with __class__.__name__, and use lazy evaluation / caching
to avoid doing the actual file-reading work more than once.

I think.

-- 
Leo Breebaart  <leo at lspace.org>



More information about the Python-list mailing list