hmm, lets call it: generic __init__ problem

Michele Simionato michele.simionato at poste.it
Wed Feb 18 12:08:32 EST 2004


paul kölle <koelle1 at uni-weimar.de> wrote in message news:<c0u0fa$1asj0f$1 at ID-131134.news.uni-berlin.de>...
> Hi list,
> 
> in the course of writing a small app, I tried to design a class, which 
> would allow to derive its behaviour solely from its name, so that I 
> would be able to write one abstract class with the logic and get 
> different objects/instances by subclassing with appropriate names. 
> Consider the following:
> 
> ATTRS = {'one':['attr1', 'attr2'],
> 	 'two':['attr3','attr4'],
> 	 'three':['attr5','attr6'],
> 	 'four':['attr7','attr8']}
> 
> 
> class one:
> 	def __init__(self, *args, **kwargs):
> 		## get allowed attributes...
> 		for attr in ATTRS[self.__class__.__name__]:
> 			self.__dict__[attr] = ''
> 
> 		## unknown attributes are silently ignored...
> 		for item in kwargs.keys():
> 			if self.__dict__.has_key( item ):
> 				 self.__dict__[item] = kwargs[item]
> 			else:
> 				 pass
> 		## init all parents...
> 		parents = self.__class__.__bases__
> 		if parents:
> 			for i in range(len(parents)):
> 			apply(parents[i].__name__.__init__,\ 								(self,)+args, kwargs)
> 

Uhm ... I am quite sure this could be done better, but it is not
completely clear what you are trying to do. The parents[i].__name__.__init__
is clearly bogus, and the loop over "i" makes me say "ickkk!".
Moreover, it is completely useless since even fixing it will generate
a recursion error (__init__ of one instance would call __init__ of
the *same* class). In principle, you would need "super", but in
this case you are probably better with "dir": dir automatically retrieves the
attributes from the parents. Here is an example:

ATTRS = {
    'one':  ['attr1', 'attr2'],
    'two':  ['attr3', 'attr4'],
    'three':['attr5', 'attr6'],
    'four': ['attr7', 'attr8']}


class one:
    def __init__(self, *args, **kwargs):
        for item in dir(self): 
            # a way to pass attributes from parents to self by hand
            if item.startswith("__"):
                pass # skip private and special names
            else:
                setattr(self,item,getattr(self,item)) #put in self.__dict__
        for attr in ATTRS[self.__class__.__name__]:
            self.__dict__[attr] = ''
        for item in kwargs.keys():
            if self.__dict__.has_key( item ):
                self.__dict__[item] = kwargs[item]
            else: #useless but may help readability
                pass
class two(one):
    def foo(self):
        pass

class three(one):
    def bar(self):
        pass

class four(two, three):
    def wiskey_bar(self):
        pass

i1=one()
i2=two()
i3=three()
i4=four()

print dir(i1)

print dir(i2)

print dir(i3)

print dir(i4)

This is probably not what you want: by I suggest you consider
changing the attributes of the class with setattr(self.__class__,name,value)
if you want inheritance to work. The issue is that the dictionary of one 
instance is local to the instance and it is not inherited, so you want to 
change the dictionary of the class.
Does this helps?

                      Michele Simionato



More information about the Python-list mailing list