raising an exception when multiple inheritance involves same baseThank

Arnaud Delobelle arnodel at googlemail.com
Sun May 25 13:21:47 EDT 2008


Sorry I lost the original post.

Paul McGuire <ptmcg at austin.rr.com> writes:

> On May 25, 8:37 am, Michael Hines <michael.hi... at yale.edu> wrote:
>> Thanks very much, Arnaud. That is exactly the hint I needed. Since it is
>> not multiple inheritance per se I prohibit but only multiple inheritance
>> involving more than one HocObject class, I replaced your len(bases) > 1
>> test with
>> <code>
>>     m = False
>>     for b in bases :
>>       if hasattr(b, '__mro__'):
>>         for bb in b.__mro__ :
>>           if bb == MetaHocObject.ho :
>>             if m == True:
>>               raise Exception("Inheritance of multiple HocObject not
>> allowed")
>>             m = True
>>
>> </code>

I think you don't need to look at the bases' mros, just use
issubclass(), e.g. (untested):

    if sum(1 for b in bases if issubclass(b, HocObject)) > 1:
        raise Exception("Multiple inheritance from HocObject")

>> to get
>>
>> class A(HocObject): pass
>>
>> class B(object): pass
>>
>> class C(): pass
>>
>> class D(C, B, HocObject): pass # ok
>>
>> class D(C, A, HocObject): pass # fail
>>
>> When I fold this idea into my code I may even try to eliminate the class
>> factory aspect of
>> class Foo(hclass(h.Vector))
>> in favor of
>> class Foo(h.Vector)
>>
>> Thanks again,
>> Michael
>
> Here's a more general version of your testing code, to detect *any*
> diamond multiple inheritance (using your sample classes).
>
> -- Paul
>
>
> for cls in (A,B,C,D):
>     seen = set()
>     try:
>         bases = cls.__bases__
>         for b in bases:
>             if hasattr(b,"__mro__"):
>                 for m in b.__mro__:
>                     if m in seen:
>                         raise Exception("diamond multiple
> inheritance")
>                     seen.add(m)
>     except Exception, e:
>         print cls,"has diamond MI"
>     else:
>         print cls,"is ok"

All new-style classes descend from object, so any new-style class
with at least two bases makes a diamond!  For example the first
version of class D above inherits twice from object, so it will be
caught.

OTOH, old-style classes don't have an __mro__, so this will not catch
diamond inheritance of old-style classes.  E.g

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

-- 
Arnaud



More information about the Python-list mailing list