Q: Meta-class usage

Discussion in 'Python' started by daishi, Dec 12, 2003.

  1. daishi

    daishi Guest

    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(object):
    def __init__(self, name):
    self.name = name

    class NamedType(type):
    def __new__(mcl, name, bases, dictionary):
    bases = tuple(list(bases)+[NamedClass])
    return super(NamedType, mcl).__new__(mcl, 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(PrintNamedType, cls).__init__(name, bases, dictionary)
    def print_name(self):
    print self.name
    setattr(cls, 'print_name', print_name)

    class NamedFoo:
    __metaclass__ = NamedType
    NAME = 'foo'

    class SubNamedFoo(NamedFoo):
    pass

    class NamedBar:
    __metaclass__ = PrintNamedType
    NAME = 'bar'
    daishi, Dec 12, 2003
    #1
    1. Advertising

  2. (daishi) writes:

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


    Apart from the fact that tuple(list(bases)+[NamedClass]) is a strange
    way of spelling bases + (NamedClass,), yes.

    > Are the semantics different from if the class with NamedType as its
    > metaclass explicitly listed NamedClass as a superclass in the
    > standard way?


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

    > 2. Is the try/except clause in NameType.__init__ the "right" way to
    > prevent KeyErrors for subclasses of classes with NamedType as its
    > metaclass?


    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
    Michael Hudson, Dec 12, 2003
    #2
    1. Advertising

  3. daishi

    daishi Guest

    Hi Michael,

    Thanks for the response. Some followup inline.

    Michael Hudson <> wrote in message news:<>...
    > (daishi) writes:
    >
    > > 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?

    >
    > Apart from the fact that tuple(list(bases)+[NamedClass]) is a strange
    > way of spelling bases + (NamedClass,), yes.


    Thanks; I had forgotten about being able to do that w/ tuples.

    >
    > > Are the semantics different from if the class with NamedType as its
    > > metaclass explicitly listed NamedClass as a superclass in the
    > > standard way?

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


    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__(mcl, 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(NamedFoo):
    File "meta2.py", line 8, in __new__
    return super(NamedType, mcl).__new__(mcl, 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.)

    > > 2. Is the try/except clause in NameType.__init__ the "right" way to
    > > prevent KeyErrors for subclasses of classes with NamedType as its
    > > metaclass?

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


    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(NamedFoo) failed
    because of the fact that since the metaclass of SubNamedFoo inherits
    from NamedFoo and hence becomes NamedType, and the NamedType.__init__
    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.

    > Cheers,
    > mwh


    Thanks again,
    d
    daishi, Dec 13, 2003
    #3
  4. (daishi) wrote in message news:<>...
    > 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.)


    Correct. More specific classes should go first to avoid confusion
    about the precedence order.

    > 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(NamedFoo) failed
    > because of the fact that since the metaclass of SubNamedFoo inherits
    > from NamedFoo and hence becomes NamedType, and the NamedType.__init__
    > 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.
    >


    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
    Michele Simionato, Dec 13, 2003
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,736
    Thomas Weidenfeller
    Oct 12, 2005
  2. Nym Pseudo

    META NAME and META HTTP-EQUIV

    Nym Pseudo, Sep 26, 2003, in forum: HTML
    Replies:
    1
    Views:
    540
    =?iso-8859-1?Q?brucie?=
    Sep 26, 2003
  3. Duane Johnson

    Meta methods to govern meta data?

    Duane Johnson, Oct 25, 2005, in forum: Ruby
    Replies:
    6
    Views:
    231
    Adam Sanderson
    Oct 28, 2005
  4. Erik Veenstra

    Meta-Meta-Programming

    Erik Veenstra, Feb 7, 2006, in forum: Ruby
    Replies:
    29
    Views:
    370
    Erik Veenstra
    Feb 8, 2006
  5. Erik Veenstra

    Meta-Meta-Programming, revisited

    Erik Veenstra, Jul 21, 2006, in forum: Ruby
    Replies:
    21
    Views:
    430
    Erik Veenstra
    Jul 25, 2006
Loading...

Share This Page