Python and generic programming

Kay Schluehr kayschluehr at gmx.de
Sun Nov 21 02:19:34 CET 2004


Jive Dadson wrote:

> How about specialization?  I'm relatively new to Python.  I ask for
> information, not to be argumentative.

There is no such thing as template specialisation or method overloading in Python 
due to the lack of static typing. 

> If you have, for example, several data-types for matrices, how do you
> write code that will automatically find the right routine for quickly
> multiplying a vector by a diagonal matrix represented as a vector, and
> automatically call the right code for multiplying by a sparse matrix
> represented by some sparse coding, etc?

Here is some code that enables automatical dispatches according to a chain of
function decorators. The chain is terminated by a decorator that does not force 
any type ( here symbolized by None ) and triggers a default function. The mul()
function in the example defines inner functions that represent different 
algorithms on different types. The mul() function itself does not return the result
of a multiplication, but the list of "specialized" inner functions ( which are in 
fact as generic as all other Python functions, but they can be regarded as
specialized in this context ).

Keep attention that the decorator chain will not work if the decorator

   @when(None,"default")

is not the last one in the chain.


# decorator function

def when(types, name):
    def push(f):        
        def eval(*t):
            funcs = []
            args  = t[3]            
            conds = [t[:2]]
            while 1:
                s = t[2](*t[3])
                if s[-1]=='stop':
                    conds.insert(0,s[:2])
                else:
                    funcs = s
                    break
                t = s            
            for (_types, funcname) in conds:
                bTypesOk = True
                if _types:
                    for (a, t) in zip(args, _types):
                        if not isinstance(a,t):
                            bTypesOk = False
                            break
                if bTypesOk:
                    for f in funcs:
                        if f.func_name == funcname:
                            return f(*args)
                else:
                    bTypesOk = True
            raise NameError,"No available function found that matches default"
                   
        def pop(*args):
            if types is None:
                return eval(types,name,f,args,"stop")
            return types,name,f,args,"stop"        
        return pop
    return push    
        
# example code

from decimal import Decimal
                
@when(None,"default")
@when((int,float),'mul_float')
@when((float,float),'mul_float')
@when((Decimal,Decimal),'mul_dec')

def mul(m1,m2):

    def default(m1,m2):
        return "default",m1*m2

    def mul_float(m1,m2):
        return "mul_float",Decimal(str(m1))*Decimal(str(m2))

    def mul_dec(m1,m2):
        return "mul_dec",m1*m2    

    return (default,mul_dec,mul_float)



Ciao
        Kay




More information about the Python-list mailing list