Q: Meta-class usage

daishi google at daishi.fastmail.fm
Sat Dec 13 01:45:45 CET 2003


Hi Michael,

Thanks for the response. Some followup inline.

Michael Hudson <mwh at python.net> wrote in message news:<m3he06awaz.fsf at pc150.maths.bris.ac.uk>...
> google at daishi.fastmail.fm (daishi) writes:
> 
> > Hi,
> > 
> > I am wondering if someone could help me understand some of the
> > details of using metaclasses.
> > 
> > I am trying to use metaclasses to auto-generate some attributes
> > and methods in a class definition. I am attaching a simplified
> > example of the kind of code I am considering below, and I have
> > the following questions:
> > 
> > 1. Is the code in NamedType.__new__ the "right" way to have a
> > class which has NamedType as its metaclass inherit from
> > NamedClass?
> 
> Apart from the fact that tuple(list(bases)+[NamedClass]) is a strange
> way of spelling bases + (NamedClass,), yes.

Thanks; I had forgotten about being able to do that w/ tuples.

> 
> > Are the semantics different from if the class with NamedType as its
> > metaclass explicitly listed NamedClass as a superclass in the
> > standard way? 
> 
> Well, potentially, depending on where in the bases list you put
> NamedClass.  In general, it might be wise to not add NamedClass to the
> bases list unless you need to (to avoid MRO calculation errors).

I was/am having some difficulties understanding what happens here.
E.g., in the example code that I gave if I make the class definition
of NamedFoo to have an explicit superclass:

class NamedFoo(object):

I obtain the error:

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "meta2.py", line 28, in ?
    class NamedFoo(object):
  File "meta2.py", line 8, in __new__
    return super(NamedType, mcl).__new__(mcl, name, bases, dictionary)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, NamedClass

If I add NamedClass to the beginning by doing:

        bases = (NamedClass,) + bases

(instead of appending to the end of bases),

I obtain the error:

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "meta2.py", line 32, in ?
    class SubNamedFoo(NamedFoo):
  File "meta2.py", line 8, in __new__
    return super(NamedType, mcl).__new__(mcl, name, bases, dictionary)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases NamedFoo, NamedClass

(Note that the error is now for class SubNamedFoo instead of
NamedFoo.)

Now based on http://www.python.org/2.3/mro.html I believe this has to
do with the fact that in the first case of NamedFoo we have
  merge([object], [NamedClass, object], [object, NamedClass])
(as opposed to
  merge([NamedClass, object], [object], [NamedClass, object])
when the modification to bases is changed)

And the SubNamedFoo error arises because of
  merge([NamedClass, object], [NamedFoo, NamedClass, object],
    [NamedClass, NamedFoo, object])

Is this correct?
(I just want to make sure that I am understanding what's going on
correctly.)

> > 2. Is the try/except clause in NameType.__init__ the "right" way to
> > prevent KeyErrors for subclasses of classes with NamedType as its
> > metaclass?
> 
> I'd say so, but I'm not totally sure what you're trying to achieve...

The basic idea of what I'm trying to do is (I think) fairly simple.
I have several fairly similar class definitions that I want, and I
was hoping to use metaclasses to make their definition more compact.
(As comparison, I would use a #define in C or a defmacro in Lisp).
I would like to use these classes once defined as if they were
regularly defined classes, included subclassing. My initial attempt
at subclassing with subclass class SubNamedFoo(NamedFoo) failed
because of the fact that since the metaclass of SubNamedFoo inherits
from NamedFoo and hence becomes NamedType, and the NamedType.__init__
is executed for SubNamedFoo also, which I didn't want - I would like
SubNamedFoo to be oblivious of the fact that NamedFoo was defined
using a customized metaclass. I was wondering what the ideal way to
achieve this might be.
 
> Cheers,
> mwh

Thanks again,
d




More information about the Python-list mailing list