|
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')] | |
Share:
|
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 | | |
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 | | This discussion thread is closed Replies have been disabled for this discussion. Similar topics
3 posts
views
Thread by Mike C. Fletcher |
last post: by
|
2 posts
views
Thread by Santiago Aguiar |
last post: by
|
27 posts
views
Thread by Michele Simionato |
last post: by
|
4 posts
views
Thread by Michael Sparks |
last post: by
|
13 posts
views
Thread by Jean-François Doyon |
last post: by
|
1 post
views
Thread by Hartmut Goebel |
last post: by
|
9 posts
views
Thread by Steffen Glückselig |
last post: by
|
1 post
views
Thread by Alan Isaac |
last post: by
|
1 post
views
Thread by Scott SA |
last post: by
| | | | | | | | | | |