Python and generic programming

Delaney, Timothy C (Timothy) tdelaney at avaya.com
Mon Nov 22 21:55:21 EST 2004


Carl Banks wrote:

>     @generic
>     def some_function(arg):
>         print "generic"
> 
>     @specializes(some_fuction,int)
>     def some_int_specific_function(arg):
>         print "int-specific"

A version that allows specialising on actual values, plus having more
than one specifier per function.

    import itertools

    def generic(genfunc):
        speclist = []
        specdict = {}

        def wrapf (arg):

            speclist2 = []

            try:
                speclist2 = specdict[arg]
            except KeyError:
                pass

            for specfunc, typ in itertools.chain(speclist2, speclist):
                try:
                    match = isinstance(arg, typ)
                except TypeError:
                    specfunc = None

                if match:
                    return specfunc(arg)

            return genfunc(arg)

        wrapf.speclist = speclist
        wrapf.specdict = specdict
        wrapf.func_name = genfunc.func_name # isn't this ok in 2.4?

        return wrapf

    def specializes(genf, *specifiers):

        try:
            while True:
                genf = genf.genfunc
        except AttributeError:
            pass
        
        def spd(specf):

            for specifier in specifiers:
                genf.speclist.append((specf, specifier))

                try:
                    genf.specdict[specifier].append((specf,
type(specifier)))
                except KeyError:
                    genf.specdict[specifier] = [(specf,
type(specifier))]

            return specf

        spd.genfunc = genf
        return spd

    # so my European friends don't get too upset
    specialises = specializes

    @generic
    def some_function(arg):
        print "generic"

    @specializes(some_function, int)
    def some_specific_function(arg):
        print "int-specific"

    @specializes(some_function, 1, 1.0)
    @specializes(some_function, 1L)
    def some_specific_function(arg):
        print "one-specific"

    some_function('abc')
    some_function(123)
    some_function(1)
    some_function(1.0)
    some_function(1L)

results in:

    generic
    int-specific
    float-specific
    one-specific
    one-specific
    one-specific

Still only deals with one argument at this point.

Tim Delaney



More information about the Python-list mailing list