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 i$02$1@news.t-online.com>...[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

    The official home of the Python Programming Language


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