question about metaclasses

S

Stephan Diehl

I have a question about metaclasses:

How would be the best way to "merge" different metaclasses?
Or, more precisely, what is the best way to merge metaclass functionality?

The idea is basicly the following:
One has several (metaclass) modules that implements an interesting feature.
Lets say, I have a metaclass L, that adds logging capabilities to all method
calls and another one, called P, that creates properties on the fly.

One possibility would be of course to write a new metaclass LP that merges
the previous two.

As far, as I can see (and I might be wrong here) the only intersting place
in a metaclass is its __new__ method where the classdict of the soon to be
created class can be manipulated.

One idea I had, was to wrap the interesting part (the manipulation of
classdict) in a function and create the actual metaclass on the fly (see
example).

Or would it be better, to create some elaborate inheritance scheme with
metaclasses (they are classes after all) ?

Thanks for your input

Stephan

--------------------------------------------------------------------------

def meta1(classname,bases,classdict):
classdict['__meta1__'] = 'meta1'

return classdict

def meta2(classname,bases,classdict):
classdict['__meta2__'] = 'meta2'

return classdict

def buildmeta(*metalist):
metalist = list(metalist)
class metameta(type):
def __new__(cls,classname,bases,classdict):
metalist.reverse()
for func in metalist:
classdict = func(classname,bases,classdict)
return type.__new__(cls,classname,bases,classdict)

return metameta

class c1(object):
__metaclass__ = buildmeta(meta1,meta2)

class c2(object):
__metaclass__ = buildmeta(meta2)

if __name__ == '__main__':
print [x for x,y in c1.__dict__.items() if x.startswith('__meta')]
print [x for x,y in c2.__dict__.items() if x.startswith('__meta')]
 
M

Michele Simionato

Stephan Diehl said:
I have a question about metaclasses:

How would be the best way to "merge" different metaclasses?
Or, more precisely, what is the best way to merge metaclass functionality?

The idea is basicly the following:
One has several (metaclass) modules that implements an interesting feature.
Lets say, I have a metaclass L, that adds logging capabilities to all method
calls and another one, called P, that creates properties on the fly.

One possibility would be of course to write a new metaclass LP that merges
the previous two.

As far, as I can see (and I might be wrong here) the only intersting place
in a metaclass is its __new__ method where the classdict of the soon to be
created class can be manipulated.

One idea I had, was to wrap the interesting part (the manipulation of
classdict) in a function and create the actual metaclass on the fly (see
example).

Or would it be better, to create some elaborate inheritance scheme with
metaclasses (they are classes after all) ?

Multiple inheritance, no doubt about that.

Whereas you could create the metaclass by hand, as you do in your example,
this way seems to me rather primitive and redundand: multiple inheritance
is there just for the the purpose of merging (meta)classes, why not to
use the facility?

Notice that 99% of times you don't need "elaborate inheritance schemes"
but just a simple diamond. The caveat is that one should use
cooperative methods; here is an example:
.... def __new__(meta,name,bases,dic):
.... print "Called M1.__new__"
.... return super(M1,meta).__new__(meta,name,bases,dic)

.... def __new__(meta,name,bases,dic):
.... print "Called M2.__new__"
.... return super(M2,meta).__new__(meta,name,bases,dic)
.... pass
.... __metaclass__=M3
Called M1.__new__
Called M2.__new__

Moreover, one must be careful about metaclass conflicts: they can
be solved with this recipe:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/204197

It is also convenient to give a look to

http://www.python.org/2.3/mro.html

in order to understand the MRO.

David Mertz and myself wrote another paper on metaclasses that should
appear on IBM developerWorks in the near future (dunno when); it covers
some of the tricky points about metaclasses that were not discussed in

http://www-106.ibm.com/developerworks/library/l-pymeta.html
Thanks for your input

Stephan

HTH,


Michele
 
S

Stephan Diehl

Michele Simionato wrote:

[...]
Notice that 99% of times you don't need "elaborate inheritance schemes"
but just a simple diamond. The caveat is that one should use
cooperative methods; here is an example:

... def __new__(meta,name,bases,dic):
... print "Called M1.__new__"
... return super(M1,meta).__new__(meta,name,bases,dic)


... def __new__(meta,name,bases,dic):
... print "Called M2.__new__"
... return super(M2,meta).__new__(meta,name,bases,dic)

... pass

... __metaclass__=M3
Called M1.__new__
Called M2.__new__

Wow. What I hadn't realized was that with the "super" builtin, both
"__new__" methods will be called on the instanciaton of C.
That is a really good one. (once in a while one really should read the
documentation :)
Thanks

Stephan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top