[Tutor] Handling function parameters of mixed object and basic types

Kent Johnson kent37 at tds.net
Mon Sep 4 15:26:38 CEST 2006


Duncan Gibson wrote:
> I've taken over someone else's code (yes, honestly!) that has a
> complex class hierarchy on top of the main procedural code. This
> is unfortunate because it means that isinstance() is everywhere.
>
> Profiling recently highlighted one particular formatted output
> function that has a cascade of isinstance() tests where the order
> of the tests is significant, as in the example:
>
>     def oldOutput(x):
>         if x is None:
>             pass
>         elif isinstance(x, Z):
>             pass
>         elif isinstance(x, Y):
>             pass
>         elif isinstance(x, X):
>             pass
>         elif isinstance(x, int):
>             pass
>         elif isinstance(x, float):
>             pass
>         elif isinstance(x, str):
>             pass
>         else:
>             pass
>
>     # NOTE:
>     # In the real code, there are various enumeration classes
>     # derived from int, so we can't even test for the built in
>     # types before we test for particular classes.

Here are two more options. output3() checks for the specific builtin 
types, rather than instances, so your EnumerationType will not be found. 
They are both faster than oldOutput for builtins other than None. 
output3 is slower than newOutput for classes because the builtins are 
tested first, but it uses OO dispatch so it is more maintainable. 
output4 is almost as fast as newOutput for class types but it will 
require changes when a new type is added.

def output3(x):
    if x is None:
        pass
    elif type(x) == int:
        pass
    elif type(x) == float:
        pass
    elif type(x) == str:
        pass
    elif type(x) == list:
        pass
    else:
        x.output()

def passer(): pass
dispatch = {
    type(None): passer,
    int: passer,
    float: passer,
    str: passer,
    list: passer,
    X: passer,
    Y: passer,
    Z: passer,
}

def output4(x):
    dispatch.get(type(x), passer)()


PS on use of timeit - it's a good idea to time multiple runs and take 
the minimum. I used min(t.repeat(number=10000)).

Kent



More information about the Tutor mailing list