another question on metaclasses

Michele Simionato mis6 at pitt.edu
Tue Dec 10 14:01:17 EST 2002


I am trying to understand metaclasses and this is my first program
using them. I post it in order to have some feedback, since I don't feel
completely confident with the subject yet. I would like to know if what I 
am doing is correct and if there are better ways to accomplish the same.

Here is the motivation for the script. It is very common to have a class
B with some __init__ method which is extended in a derived class C:

class B(object):
    def __init__(self,*args,**kw):
        print "This is B.__init__"

class C(B):
    def __init__(self,*args,**kw):
	  B.__init__(self,*args,**kw)
        print "This is C.__init__"

Notice that the B.__init__ method has to be called explicitly. In general
this is fine, but in some cases it would be handy to have B.__init__ called
automatically. To perform this, I used metaclasses:

-------------- begin MetaInit.py -----------------------

class MetaInit(type):
    """If cls inherits from bases, and cls.__metaclass__==MetaInit, then
    cls.__init__ is extended to call super(cls).__init__ ."""
    def __init__(cls,name,bases,dict):
        child_init=cls.__init__ #makes a copy ?
        def double_init(self,*args,**kw):
            "Both the super and the child __init__ are called"
            super(cls,self).__init__(self,*args,**kw)
            child_init(self,*args,**kw)
        setattr(cls,'__init__',double_init)

class Autoinit(object):
    """Autoinit should be thought as a mixin class. Classes derived from
    Autoinit automagically call their super __init__ methods according to
    the MRO. The magic works because Autoinit-derived classes inherit the 
    Autoinit metaclass MetaInit. Notice that Autounit itself inherit its 
    __init__  method from object, which does nothing."""
    __metaclass__ = MetaInit
    
class B(Autoinit):
    def __init__(self,*args,**kw):
        print "This is B.__init__"

class C(Autoinit):
    def __init__(self,*args,**kw):
        print "This is C.__init__"

class D(B,C):
    def __init__(self,*args,**kw):
        print "This is D.__init__"

d=D()

------- end MetaInit.py -------

The output of this program is 

This is C.__init__
This is B.__init__
This is D.__init__

i.e. what I want. Nevertheless, I wonder if there are cases where this script 
could break down, then I ask the Python gurus for comments and feedback.
TIA,


--
Michele Simionato - Dept. of Physics and Astronomy
210 Allen Hall Pittsburgh PA 15260 U.S.A.
Phone: 001-412-624-9041 Fax: 001-412-624-9163
Home-page: http://www.phyast.pitt.edu/~micheles/



More information about the Python-list mailing list