hmm, lets call it: generic __init__ problem
Peter Otten
__peter__ at web.de
Wed Feb 18 04:33:41 EST 2004
paul kölle wrote:
> 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:
[quotes as mutilated by my news reader :-(]
> 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
Superfluous 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)
In current python:
for parent in parents:
parent.__name__.__init__(self, *args, **kwargs)
However, you are calling the __init__() method of a string (parent.__name__)
which is a noop as strings are immutable (I'm surprised it didn't fail).
I suppose you intended to call parent.__init__() which would result in
infinite recursion as you determine the class to operate on by
self.__class__ which will always be the same.
I think this is what you want:
ATTRS = {'one':['attr1', 'attr2'],
'two':['attr3','attr4'],
'three':['attr5','attr6'],
'four':['attr7','attr8']}
class one:
def __init__(self, **kwargs):
## get allowed attributes...
classes = [self.__class__]
while classes:
cls = classes.pop(0)
for attr in ATTRS[cls.__name__]:
self.__dict__[attr] = ''
classes.extend(cls.__bases__)
## unknown attributes are silently ignored...
for key, value in kwargs.iteritems():
if key in self.__dict__:
self.__dict__[key] = value
class two(one):
def foo(self):
pass
class three(one):
def bar(self):
pass
class four(two, three):
def wiskey_bar(self):
pass
params = dict(attr1="a", attr3="b", attr5="c", attr7="d")
for klass in [one, two, three, four]:
obj = klass(**params)
print klass.__name__
print "\t", [a for a in dir(obj) if not a.startswith("_")]
> Apart from the obvious mistake I can't figure out:
> 1) Is this intelligent at all?
Is there a polite way of saying no?
Seriously, have a look at the tutorial to get uptodate with the current
python features, then set yourself a real task and try to solve it in the
simplest and cleanest manner. I am confident that you will *not* need
multiple inheritance or attributes with pointless default values.
IMHO silently ignoring anything is strongly against python's philosophy.
> 2) Is there a better way to do it?
I'm sure there would be if only I knew what *it* is meant to be.
> 3) How do you change tabwidth in mozilla mail?
No idea, but changing from tabs to spaces is urgent, as you can see from the
quotes.
Peter
More information about the Python-list
mailing list