question about metaclasses

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Stephan Diehl

    question about metaclasses

    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,classdic t):
    classdict['__meta1__'] = 'meta1'

    return classdict

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

    return classdict

    def buildmeta(*meta list):
    metalist = list(metalist)
    class metameta(type):
    def __new__(cls,cla ssname,bases,cl assdict):
    metalist.revers e()
    for func in metalist:
    classdict = func(classname, bases,classdict )
    return type.__new__(cl s,classname,bas es,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__.ite ms() if x.startswith('_ _meta')]
    print [x for x,y in c2.__dict__.ite ms() if x.startswith('_ _meta')]

  • Michele Simionato

    #2
    Re: question about metaclasses

    Stephan Diehl <stephan.diehl@ gmx.net> wrote in message news:<bdp39a$do [email protected]>...[color=blue]
    > 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) ?[/color]

    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:
    [color=blue][color=green][color=darkred]
    >>> class M1(type):[/color][/color][/color]
    .... def __new__(meta,na me,bases,dic):
    .... print "Called M1.__new__"
    .... return super(M1,meta). __new__(meta,na me,bases,dic)

    [color=blue][color=green][color=darkred]
    >>> class M2(type):[/color][/color][/color]
    .... def __new__(meta,na me,bases,dic):
    .... print "Called M2.__new__"
    .... return super(M2,meta). __new__(meta,na me,bases,dic)
    [color=blue][color=green][color=darkred]
    >>> class M3(M1,M2):[/color][/color][/color]
    .... pass
    [color=blue][color=green][color=darkred]
    >>> class C:[/color][/color][/color]
    .... __metaclass__=M 3
    Called M1.__new__
    Called M2.__new__

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



    It is also convenient to give a look to



    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


    [color=blue]
    > Thanks for your input
    >
    > Stephan[/color]

    HTH,


    Michele

    Comment

    • Stephan Diehl

      #3
      Re: question about metaclasses

      Michele Simionato wrote:

      [...][color=blue]
      >
      > 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:
      >[color=green][color=darkred]
      >>>> class M1(type):[/color][/color]
      > ... def __new__(meta,na me,bases,dic):
      > ... print "Called M1.__new__"
      > ... return super(M1,meta). __new__(meta,na me,bases,dic)
      >
      >[color=green][color=darkred]
      >>>> class M2(type):[/color][/color]
      > ... def __new__(meta,na me,bases,dic):
      > ... print "Called M2.__new__"
      > ... return super(M2,meta). __new__(meta,na me,bases,dic)
      >[color=green][color=darkred]
      >>>> class M3(M1,M2):[/color][/color]
      > ... pass
      >[color=green][color=darkred]
      >>>> class C:[/color][/color]
      > ... __metaclass__=M 3
      > Called M1.__new__
      > Called M2.__new__
      >[/color]

      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

      Comment

      Working...