hmm, lets call it: generic __init__ problem

Peter Otten __peter__ at
Wed Feb 18 10:33:41 CET 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'],

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] = ''

        ## 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):

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

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

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


More information about the Python-list mailing list