On Fri, Apr 15, 2011 at 11:30 PM, Michael Foord <fuzzy...@voidspace.org.uk> wrote: > On 15/04/2011 02:02, Greg Ewing wrote: >> There isn't necessarily a clear distinction between parents >> and siblings. >> >> class A: >> ... >> >> class B(A): >> ... >> >> class C(A, B): >> ... >> >> In C, is A a parent of B or a sibling of B?
As has been pointed out elsewhere in the thread, that definition of C isn't allowed :) >>> class C(A, B): pass ... Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Cannot create a consistent method resolution order (MRO) for bases A, B Once you turn the order of definition around (class C(B, A)) it becomes clear that A remains B's parent regardless of the existence of C: >>> C.__mro__ (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) The whole discussion of trying to distinguish parents from siblings when invoking super() *doesn't make sense*. The entire *point* of the multiple inheritance handling is to linearise the type hierarchy into a method resolution order that consists of a single chain of classes that are called in sequence (with any class in the chain allowed to terminate the sequence at any time). Cooperative super() calls are exactly that: cooperative. Just as cooperative threading breaks down if one task doesn't play by the rules, such is also the case with cooperative super calls. There are two ways to handle this: - Option 1 is to tailor your inheritance hierarchy such that any "non-cooperative" classes always appear on the right-most end of the MRO (e.g. as "A" and "object" do in the example above). This can be tricky, but is doable if there is just the one recalcitrant class causing problems (e.g. I wouldn't be surprised to hear that a simple rearrangement to "class MyTestCase(Mixin1, Mixin2, TestCase)" sufficiently rearranged the "MyTestCase" MRO to make this problem go away). - Option 2 is to do as Raymond suggests: noncooperative classes are incorporated via "has-a" composition (potentially as a proxy object) rather than "is-a" inheritance. For any methods which require cooperative calls, the cooperative wrapper provides that behaviour, while delegating the heavy lifting to the underlying object. Essentially, any cooperative hierarchy requires a base class that defines the rules of cooperation and provides "no-op" termination methods for any cooperative calls. Non-cooperative classes must either be parents of that base class, or else they must be wrapped as described in Option 2. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com