> B1.fun(A(x), A(y), A(z)) == B.fun(A(x), A(y), A(z)) > but > B1.fun(A1(x), A(y), A(z) != B.fun(A1(x), A(y), A(z)) > > Is there a data-structure solution or third party module that would > mimic this behavior?
''' An Overloaded instance, B.xfun, is created in the base class of the classes the members of which you want to override. Define the function you want to override, merely to call 'invoke' on it. xfun.make( typeA, typeB ) is a wrapper which will bind the type- function pair to it as well. Define any number of these. When the class is complete, call B.xfun.push with the class just defined, to let xfun know that the methods just bound were defined in it. Perhaps future Pythons will allow a class currently being executed to be referenced. Class decorators will be able to permit this as well: @xfun.push / class B1( B ). (Anyone know why I got this: "TypeError: cannot create 'NoneType' instances"?) Upon calling B().fun( A(), A(), A() ), B.fun, the root of all funs, calls dispatch on the instance. In theory it could be called directly with the right binding. Dispatch then checks the types of the arguments, and tries successively higher subclass types on the class instance, until it finds a combination of types that was defined. If none is found, raise a TypeError. If you want a behavior to occur by default, without a matching type sequence, let me know; or do it yourself, either with a try: except: combination in B.fun, the dispatcher for the bound method, or by testing for a match in it, upon succeeding, call that, and upon failing, do the default. ''' class A: pass class A1: pass class Overloaded: def __init__( self ): self._tps= {} self._pend= {} def make( self, *tps ): def _pre( func ): self._pend[ tps ]= func return func return _pre def dispatch( self, objself, *a ): tps= tuple( type( i ) for i in a ) for c in objself.__class__.__mro__: if ( c, )+ tps in self._tps: match= self._tps[ ( c, )+ tps ] return match( objself, *a ) raise TypeError( 'No matching type' 'signature for %s %s types %s %s'% ( objself, a, type( objself ), tps ) ) def push( self, tp ): for k, v in self._pend.items(): self._tps[ ( tp, )+ k ]= v self._pend.clear() class B: xfun= Overloaded() def fun( self, *a ): return self.xfun.dispatch( self, *a ) @xfun.make( A, A, A ) def q( self, x, y, z ): return 'B AAA' @xfun.make( A1, A, A ) def q( self, x, y, z ): return 'B A1AA' B.xfun.push( B ) class B1(B): @B.xfun.make( A1, A, A ) def q( self, x, y, z ): return 'B1 A1AA' B.xfun.push( B1 ) class B2(B1): @B.xfun.make( A, A, A ) def q( self, x, y, z ): return 'B2 AAA' B.xfun.push( B2 ) class B3(B1): @B.xfun.make( A1, A, A ) def q( self, x, y, z ): return 'B3 A1AA' B.xfun.push( B3 ) b= B() assert b.fun( A(), A(), A() )== 'B AAA' assert b.fun( A1(), A(), A() )== 'B A1AA' b1= B1() assert b1.fun( A1(), A(), A() )== 'B1 A1AA' assert b1.fun( A(), A(), A() )== 'B AAA' b2= B2() assert b2.fun( A1(), A(), A() )== 'B1 A1AA' assert b2.fun( A(), A(), A() )== 'B2 AAA' b3= B3() assert b3.fun( A1(), A(), A() )== 'B3 A1AA' assert b3.fun( A(), A(), A() )== 'B AAA' try: assert b3.fun( A(), A1(), A() )== 'B AAA' assert False, 'Type matched incorrectly' except TypeError: pass print( 'Pass.' ) ''' This is a somewhat advanced technique. If you're not using Python 3.0, let me know, and I'll add inheritance arguments to Overloaded.push, to replace .__mro__ in Overloaded.dispatch. ''' -- http://mail.python.org/mailman/listinfo/python-list