Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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 = {'CA':'San Diego', 'NY':'New York', 'MI':'Detroit'}

# 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.

share|improve this question
5  
Why would this post be off-topic? It's a great algorithm and data structure concept question! –  Martijn Pieters Jan 9 '13 at 20:52
    
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. –  KChaloux Jan 9 '13 at 21:17
1  
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? –  mdeutschmtl Jan 10 '13 at 22:31
add comment

4 Answers

up vote 25 down vote accepted

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 = dict(
    '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.

share|improve this answer
1  
@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 Jan 10 '13 at 2:03
    
@PhD: Yeah, the example I built is a Command Pattern implementation; the dict acts as the dispatcher (command manager, invoker, etc.). –  Martijn Pieters Jan 10 '13 at 7:02
    
Great top-level explanation, @Martijn, thanks. I think I get the "dispatch" idea. –  mdeutschmtl Jan 10 '13 at 22:25
add comment

@Martijn Pieters did a good job explaining the technique, but I wanted to clarify something from your question.

The important thing to know is that you are NOT storing "the name of the function" in the dictionary. You are storing a reference to the function itself. You can see this using a print on the function.

>>> def f():
...   print 1
... 
>>> print f
<function f at 0xb721c1b4>

f is just a variable that references the function you defined. Using a dictionary allows you to group like things, but it isn't any different from assigning a function to a different variable.

>>> a = f
>>> a
<function f at 0xb721c3ac>
>>> a()
1

Similarly, you can pass a function as an argument.

>>> def c(func):
...   func()
... 
>>> c(f)
1
share|improve this answer
1  
Mentioning first class function would definitely help :-) –  Florian Margaine Jan 9 '13 at 20:32
add comment

Note that Python class is really just a syntax sugar for dictionary. When you do:

class Foo(object):
    def find_city(self, city):
        ...

when you call

f = Foo()
f.find_city('bar')

is really just the same as:

getattr(f, 'find_city')('bar')

which, after name resolution, is just the same as:

f.__class__.__dict__['find_city'](f, 'bar')

One useful technique is for mapping user input to callbacks. For example:

def cb1(...): 
    ...
funcs = {
    'cb1': cb1,
    ...
}
while True:
    input = raw_input()
    funcs[input]()

This can alternatively be written in class:

class Funcs(object):
    def cb1(self, a): 
        ...
funcs = Funcs()
while True:
    input = raw_input()
    getattr(funcs, input)()

whichever callback syntax is better depends on the particular application and programmer's taste. The former is more functional style, the latter is more object oriented. The former might feel more natural if you need to modify the entries in the function dictionary dynamically (perhaps based on user input); the latter might feel more natural if you have a set of different presets mapping that can be chosen dynamically.

share|improve this answer
    
I think this interchangeability is what made me think "pythonic", the fact that what you see on the surface is just a conventional way of presenting something much deeper. Maybe that's not particular to python, though python exercises (and python programmers?) do seem to talk an awful lot about language features this way. –  mdeutschmtl Jan 10 '13 at 22:20
    
Another thought, is there something specific to python in the way it is willing to evaluate what looks like two "terms" just sitting adjacent to each other, the dict reference and the argument list? Do other languages allow that? It's sort of the programming equivalent of the leap in algebra from 5 * x to 5x (forgive the simple analogy). –  mdeutschmtl Jan 10 '13 at 22:29
    
@mdeutschmtl: it's not really unique to Python, although languages which lack first class function or function object may never have any situations where a dictionary access immediately followed by function call could be possible. –  Lie Ryan Jan 11 '13 at 8:07
add comment

There are 2 techniques that leap to my mind which you may be referring to, neither of which are Pythonic in that they are more broad than one language.

1. The technique of information hiding/encapsulation and cohesion (they usually go hand in hand so I'm lumping them together).

You have an object which has data, and you attaching a method (behavior) which is highly cohesive with the data. Should you need to change the function, extend the functionality or make any other changes the callers will not need to change (assuming no additional data needs to be passed in).

2. Dispatch tables

Not the classic case, because there is only one entry with a function. However, dispatch tables are used to organize different behaviors by a key such that they can looked up and called dynamically. I'm not sure if your thinking of this since your not referring to the function in a dynamic way, but none the less you still gain effective late binding (the "indirect" call).

Tradeoffs

One thing to note is what your doing will work fine with a known namespace of keys. However, you run the risk of collision between the data and the functions with an unknown namespace of keys.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.