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