Why store a function inside a python dictionary?

  • I'm a python beginner, and I just learned a technique involving dictionaries and functions. The syntax is easy and it seems like a trivial thing, but my python senses are tingling. Something tells me this is a deep and very pythonic concept and I'm not quite grasping its importance. Can someone put a name to this technique and explain how/why it's useful?


    The technique is when you have a python dictionary and a function that you intend to use on it. You insert an extra element into the dict, whose value is the name of the function. When you're ready to call the function you issue the call indirectly by referring to the dict element, not the function by name.

    The example I'm working from is from Learn Python the Hard Way, 2nd Ed. (This is the version available when you sign up through Udemy.com; sadly the live free HTML version is currently Ed 3, and no longer includes this example).

    To paraphrase:

    # make a dictionary of US states and major cities
    cities = {'San Diego':'CA', 'New York':'NY', 'Detroit':'MI'}
    
    # define a function to use on such a dictionary
    def find_city (map, city):
        # does something, returns some value
        if city in map:
            return map[city]
        else:
            return "Not found"
    
    # then add a final dict element that refers to the function
    cities['_found'] = find_city
    

    Then the following expressions are equivalent. You can call the function directly, or by referencing the dict element whose value is the function.

    >>> find_city (cities, 'New York')
    NY
    
    >>> cities['_found'](cities, 'New York')
    NY
    

    Can someone explain what language feature this is, and maybe where it comes to play in "real" programming? This toy exercise was enough to teach me the syntax, but didn't take me all the way there.

    Why would this post be off-topic? It's a great algorithm and data structure concept question!

    I've seen (and done) some stuff like this in other languages. You could sort of look at it as a switch statement, but wrapped up nicely in a passable object with O(1) lookup time.

    I had a hunch there was something important & self-referential about including the function inside its own dict... see @dietbuddha's answer... but maybe not?

  • Using a dict let's you translate the key into a callable. The key doesn't need to be hardcoded though, as in your example.

    Usually, this is a form of caller dispatch, where you use the value of a variable to connect to a function. Say a network process sends you command codes, a dispatch mapping lets you translate the command codes easily into executable code:

    def do_ping(self, arg):
        return 'Pong, {0}!'.format(arg)
    
    def do_ls(self, arg):
        return '\n'.join(os.listdir(arg))
    
    dispatch = {
        'ping': do_ping,
        'ls': do_ls,
    }
    
    def process_network_command(command, arg):
        send(dispatch[command](arg))
    

    Note that what function we call now depends entirely on what the value is of command. The key doesn't have to match either; it doesn't even have to be a string, you could use anything that can be used as a key, and fits your specific application.

    Using a dispatch method is safer than other techniques, such as eval(), as it limits the commands allowable to what you defined beforehand. No attacker is going to sneak a ls)"; DROP TABLE Students; -- injection past a dispatch table, for example.

    @Martjin - Couldn't this be called an implementation of the 'Command Pattern' in that case? Seems like that's the concept the OP is trying to grasp?

    @PhD: Yeah, the example I built is a Command Pattern implementation; the `dict` acts as the dispatcher (command manager, invoker, etc.).

    Great top-level explanation, @Martijn, thanks. I think I get the "dispatch" idea.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM