Q: Meta-class usage

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

    Q: Meta-class usage

    Hi,

    I am wondering if someone could help me understand some of the
    details of using metaclasses.

    I am trying to use metaclasses to auto-generate some attributes
    and methods in a class definition. I am attaching a simplified
    example of the kind of code I am considering below, and I have
    the following questions:

    1. Is the code in NamedType.__new __ the "right" way to have a
    class which has NamedType as its metaclass inherit from
    NamedClass? Are the semantics different from if the class with
    NamedType as its metaclass explicitly listed NamedClass as a
    superclass in the standard way?
    2. Is the try/except clause in NameType.__init __ the "right"
    way to prevent KeyErrors for subclasses of classes with
    NamedType as its metaclass?

    Thanks in advance,
    d

    ---
    class NamedClass(obje ct):
    def __init__(self, name):
    self.name = name

    class NamedType(type) :
    def __new__(mcl, name, bases, dictionary):
    bases = tuple(list(base s)+[NamedClass])
    return super(NamedType , mcl).__new__(mc l, name, bases, dictionary)
    def __init__(cls, name, bases, dictionary):
    try:
    name = dictionary['NAME']
    except KeyError:
    return
    def is_a(self):
    return self.name == name
    setattr(cls, 'is_a_'+name, is_a)
    def init(self):
    super(cls, self).__init__( name)
    setattr(cls, '__init__', init)

    class PrintNamedType( NamedType):
    def __init__(cls, name, bases, dictionary):
    super(PrintName dType, cls).__init__(n ame, bases, dictionary)
    def print_name(self ):
    print self.name
    setattr(cls, 'print_name', print_name)

    class NamedFoo:
    __metaclass__ = NamedType
    NAME = 'foo'

    class SubNamedFoo(Nam edFoo):
    pass

    class NamedBar:
    __metaclass__ = PrintNamedType
    NAME = 'bar'
  • Michael Hudson

    #2
    Re: Q: Meta-class usage

    google@daishi.f astmail.fm (daishi) writes:
    [color=blue]
    > Hi,
    >
    > I am wondering if someone could help me understand some of the
    > details of using metaclasses.
    >
    > I am trying to use metaclasses to auto-generate some attributes
    > and methods in a class definition. I am attaching a simplified
    > example of the kind of code I am considering below, and I have
    > the following questions:
    >
    > 1. Is the code in NamedType.__new __ the "right" way to have a
    > class which has NamedType as its metaclass inherit from
    > NamedClass?[/color]

    Apart from the fact that tuple(list(base s)+[NamedClass]) is a strange
    way of spelling bases + (NamedClass,), yes.
    [color=blue]
    > Are the semantics different from if the class with NamedType as its
    > metaclass explicitly listed NamedClass as a superclass in the
    > standard way?[/color]

    Well, potentially, depending on where in the bases list you put
    NamedClass. In general, it might be wise to not add NamedClass to the
    bases list unless you need to (to avoid MRO calculation errors).
    [color=blue]
    > 2. Is the try/except clause in NameType.__init __ the "right" way to
    > prevent KeyErrors for subclasses of classes with NamedType as its
    > metaclass?[/color]

    I'd say so, but I'm not totally sure what you're trying to achieve...

    Cheers,
    mwh

    --
    The Internet is full. Go away.
    -- http://www.disobey.com/devilshat/ds011101.htm

    Comment

    • daishi

      #3
      Re: Q: Meta-class usage

      Hi Michael,

      Thanks for the response. Some followup inline.

      Michael Hudson <mwh@python.net > wrote in message news:<m3he06awa z.fsf@pc150.mat hs.bris.ac.uk>. ..[color=blue]
      > google@daishi.f astmail.fm (daishi) writes:
      >[color=green]
      > > Hi,
      > >
      > > I am wondering if someone could help me understand some of the
      > > details of using metaclasses.
      > >
      > > I am trying to use metaclasses to auto-generate some attributes
      > > and methods in a class definition. I am attaching a simplified
      > > example of the kind of code I am considering below, and I have
      > > the following questions:
      > >
      > > 1. Is the code in NamedType.__new __ the "right" way to have a
      > > class which has NamedType as its metaclass inherit from
      > > NamedClass?[/color]
      >
      > Apart from the fact that tuple(list(base s)+[NamedClass]) is a strange
      > way of spelling bases + (NamedClass,), yes.[/color]

      Thanks; I had forgotten about being able to do that w/ tuples.
      [color=blue]
      >[color=green]
      > > Are the semantics different from if the class with NamedType as its
      > > metaclass explicitly listed NamedClass as a superclass in the
      > > standard way?[/color]
      >
      > Well, potentially, depending on where in the bases list you put
      > NamedClass. In general, it might be wise to not add NamedClass to the
      > bases list unless you need to (to avoid MRO calculation errors).[/color]

      I was/am having some difficulties understanding what happens here.
      E.g., in the example code that I gave if I make the class definition
      of NamedFoo to have an explicit superclass:

      class NamedFoo(object ):

      I obtain the error:

      Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "meta2.py", line 28, in ?
      class NamedFoo(object ):
      File "meta2.py", line 8, in __new__
      return super(NamedType , mcl).__new__(mc l, name, bases, dictionary)
      TypeError: Cannot create a consistent method resolution
      order (MRO) for bases object, NamedClass

      If I add NamedClass to the beginning by doing:

      bases = (NamedClass,) + bases

      (instead of appending to the end of bases),

      I obtain the error:

      Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "meta2.py", line 32, in ?
      class SubNamedFoo(Nam edFoo):
      File "meta2.py", line 8, in __new__
      return super(NamedType , mcl).__new__(mc l, name, bases, dictionary)
      TypeError: Cannot create a consistent method resolution
      order (MRO) for bases NamedFoo, NamedClass

      (Note that the error is now for class SubNamedFoo instead of
      NamedFoo.)

      Now based on http://www.python.org/2.3/mro.html I believe this has to
      do with the fact that in the first case of NamedFoo we have
      merge([object], [NamedClass, object], [object, NamedClass])
      (as opposed to
      merge([NamedClass, object], [object], [NamedClass, object])
      when the modification to bases is changed)

      And the SubNamedFoo error arises because of
      merge([NamedClass, object], [NamedFoo, NamedClass, object],
      [NamedClass, NamedFoo, object])

      Is this correct?
      (I just want to make sure that I am understanding what's going on
      correctly.)
      [color=blue][color=green]
      > > 2. Is the try/except clause in NameType.__init __ the "right" way to
      > > prevent KeyErrors for subclasses of classes with NamedType as its
      > > metaclass?[/color]
      >
      > I'd say so, but I'm not totally sure what you're trying to achieve...[/color]

      The basic idea of what I'm trying to do is (I think) fairly simple.
      I have several fairly similar class definitions that I want, and I
      was hoping to use metaclasses to make their definition more compact.
      (As comparison, I would use a #define in C or a defmacro in Lisp).
      I would like to use these classes once defined as if they were
      regularly defined classes, included subclassing. My initial attempt
      at subclassing with subclass class SubNamedFoo(Nam edFoo) failed
      because of the fact that since the metaclass of SubNamedFoo inherits
      from NamedFoo and hence becomes NamedType, and the NamedType.__ini t__
      is executed for SubNamedFoo also, which I didn't want - I would like
      SubNamedFoo to be oblivious of the fact that NamedFoo was defined
      using a customized metaclass. I was wondering what the ideal way to
      achieve this might be.
      [color=blue]
      > Cheers,
      > mwh[/color]

      Thanks again,
      d

      Comment

      • Michele Simionato

        #4
        Re: Q: Meta-class usage

        google@daishi.f astmail.fm (daishi) wrote in message news:<d22692a3. 0312121645.7f99 cfd1@posting.go ogle.com>...[color=blue]
        > Now based on http://www.python.org/2.3/mro.html I believe this has to
        > do with the fact that in the first case of NamedFoo we have
        > merge([object], [NamedClass, object], [object, NamedClass])
        > (as opposed to
        > merge([NamedClass, object], [object], [NamedClass, object])
        > when the modification to bases is changed)
        >
        > And the SubNamedFoo error arises because of
        > merge([NamedClass, object], [NamedFoo, NamedClass, object],
        > [NamedClass, NamedFoo, object])
        >
        > Is this correct?
        > (I just want to make sure that I am understanding what's going on
        > correctly.)[/color]

        Correct. More specific classes should go first to avoid confusion
        about the precedence order.
        [color=blue]
        > The basic idea of what I'm trying to do is (I think) fairly simple.
        > I have several fairly similar class definitions that I want, and I
        > was hoping to use metaclasses to make their definition more compact.
        > (As comparison, I would use a #define in C or a defmacro in Lisp).
        > I would like to use these classes once defined as if they were
        > regularly defined classes, included subclassing. My initial attempt
        > at subclassing with subclass class SubNamedFoo(Nam edFoo) failed
        > because of the fact that since the metaclass of SubNamedFoo inherits
        > from NamedFoo and hence becomes NamedType, and the NamedType.__ini t__
        > is executed for SubNamedFoo also, which I didn't want - I would like
        > SubNamedFoo to be oblivious of the fact that NamedFoo was defined
        > using a customized metaclass. I was wondering what the ideal way to
        > achieve this might be.
        >[/color]

        Maybe a simple function acting as a class factory? Sometimes the
        simplest solutions are the best solutions. So, unless you anticipate
        the need to use inheritance of metaclasses, why don't you use a simple
        function return a class (created with type(name,bases ,dic), the basic
        metaclass) ?

        Michele

        Comment

        Working...