Search code examples
pythonpython-2.7generic-functionsingle-dispatch

How can I dispatch Python 2 functions based on the data type passed to the function?


I would like to dispatch Python functions dependent (e.g. using a dict approach) on the data type of the argument passed to the "dispatching" function (e.g. using isinstance()). Are there implementation alternatives? What's the easiest approach?


Solution

  • As of Python 3.4, the Python standard library includes support for @singledispatch() generic functions.

    This lets you register multiple functions to handle different types, and it'll handle dispatch based on type, including subclass testing and caching. The method is described in PEP 443 - Single-dispatch generic functions.

    There is a backport available on PyPI that supports Python 2.6 and up, written by the PEP author.

    Note that Python 2.7 will soon be hitting a final end-of-life date, where it'll no longer receive bug fixes and security updates; you really need to plan for upgrading to Python 3 sooner rather than later. When you do, you'll note that the Python 3.7 version supports using type hinting to document what type each function accepts.

    For example, a series of functions to remove None and False values from a nested dictionary-and-list data structure (a typical JSON data structure), can be defined as:

    from functools import singledispatch
    
    @singledispatch
    def remove_null_false(ob):
        return ob
    
    @remove_null_false.register
    def _process_list(ob: list):
        return [remove_null_false(v) for v in ob]
    
    @remove_null_false.register
    def _process_list(ob: dict):
        return {k: remove_null_false(v) for k, v in ob.items()
                if v is not None and v is not True and v is not False}
    

    In Python versions < 3.7 you'd have to move the type to the @remove_null_false.register(...) decorator factory notation.