hmm, lets call it: generic __init__ problem

Peter Otten __peter__ at web.de
Wed Feb 18 08:12:12 EST 2004


paul kölle wrote:

> To be honest, it is a "real world" (if there is any) task. The funClass
> thing was just to isolate the problem. I'm writing an LDAP client and
> the data model is made up of ObjectClasses which in turn have required
> and optional attributes. ObjectClasses can inherit attributes from
> "superior" ObjectClasses and the actual dataset (entry) may consist of
> multiple ObjectClasses, collecting all their attributes.
> 
> I thought it would be a good idea to mimic that with classes in the
> client code by naming the classes like the ObjectClasses and get the
> required and allowed attributes of the instance from the server in
> __init__ like:
> r = self.schema.get_obj(ldap.schema.ObjectClass,\ self.__class__.__name__)
> ...process r...
> 
> This has to be done for every parent and the whole point was *not* to
> write another __init__ for each subclass. So the question boils down to:
> 
> 1) Do I have to call Super.__init__ explicitely in: Child(Super)'s
> __init__ method  ?

Yes. (But there's a workaround, see below)
 
> 2) If 1): Since I do not want to write a new __init__ for every possible
> subclass, how do I call Super.__init__ if I do not know Super's name?

super() comes to the rescue. If you follow c.l.py you'll notice that there
are pitfalls, though. http://www.python.org/2.2/descrintro.html#cooperation
might be useful. 

>>> def makeClass(attributes):
...     class A(object):
...             def __init__(self, **kw):
...                     super(A, self).__init__(**kw) # this does the magic
...                     for a in attributes:
...                             setattr(self, a, kw.get(a, ""))
...     return A
...
>>> A = makeClass("abc") # use a list of attribute names in real code
>>> B = makeClass("xyz")
>>> class C(A,B):
...     pass
...
>>> c = C(**dict(zip("abklxy", range(6))))
>>> c.a # initialized by keyword arg
0
>>> c.c # set to default value
''
>>> c.k # silently ignored
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'C' object has no attribute 'k'
>>>

The makeClass() factory is not strictly needed. Just remember to derive
every base class from object and call

super(CurrentClass, self).__init__() 

in its __init() method.


Peter




More information about the Python-list mailing list