By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,172 Members | 1,751 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,172 IT Pros & Developers. It's quick & easy.

question about metaclasses

P: n/a
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')]

Jul 18 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Stephan Diehl <st***********@gmx.net> wrote in message news:<bd*************@news.t-online.com>...
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:
class M1(type): .... def __new__(meta,name,bases,dic):
.... print "Called M1.__new__"
.... return super(M1,meta).__new__(meta,name,bases,dic)

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

.... __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/Coo.../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/developerwork.../l-pymeta.html
Thanks for your input

Stephan


HTH,
Michele
Jul 18 '05 #2

P: n/a
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:
class M1(type): ... def __new__(meta,name,bases,dic):
... print "Called M1.__new__"
... return super(M1,meta).__new__(meta,name,bases,dic)

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

... __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

Jul 18 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.