[Tutor] Using dictionaries to call functione
Danny Yoo
dyoo@hkn.eecs.berkeley.edu
Fri, 17 Aug 2001 11:17:07 -0700 (PDT)
On Fri, 17 Aug 2001, dman wrote:
> On Fri, Aug 17, 2001 at 09:14:23AM -0500, Kevin McCormick wrote:
> | I have seen several examples of using dictionaries to call functions. I
> | believe the function name is the dictionary key, and its values are the
> | associated arguments. Yet, I find this method difficult to understand.
> | For example, I would like to pass a list of words and parameters to a
> | function, and for each word in the list, call word(parameter1,
> | parameter2, ...) referenced in a dictionary which somehow calls the
> | associated function (called a "dispatch table", I think). What are the
> | basic concepts of this method?
>
> In python, functions are objects just like everything else. This
> means that they can be stored in a dictionary. The key can be
> anything you want it to be, but is often a string or integer that is
> directly related to some input. The value is just a reference to the
> function. The client would retrieve that function object from the
> dictionary then call it just as it would any other function. The only
> trick is to make sure that the client knows what sort of arguments the
> function expects. Here is an example :
>
> def func1( p1 , p2 ) :
> print "func1 called : %s , %s" % (p1 , p2)
>
> def func2( p1 , p2 ) :
> print "func2 called : %s , %s" % (p1 , p2)
>
>
> dispatch_table = {
> "hello" : func1 ,
> "bye" : func2
> }
We can also write this so that the dispatcher doesn't even think about how
many arguments each function takes in:
###
def callFunction(function_name, arguments):
the_func = dispatch_table[function_name]
the_func(*arguments)
if __name__ == "__main__" :
import sys
if not dispatch_table.has_key( sys.argv[1] ) :
print "Unknown command '%s'" % sys.argv[1]
sys.exit( 1 )
callFunction(sys.argv[1], sys.argv[2:])
###
The star in front of 'arguments' is what tells Python to send off the
elements of 'arguments' to the_func().
Although this simplifies the code a little, now the program will die if we
give the function too many arguments, or not enough. That's where
exception handling comes in: we can put the code in a try/except block
that knows what to do when the user doesn't give enough arguments.
Here's another example that demonstrates a little bit of exception
handling as well as the dispatch approach:
###
"""This is a small example of dispatch-based programming.
Danny Yoo (dyoo@hkn.eecs.berkeley.edu)
"""
import sys
def addCommand(*args):
sum = 0
for thing in args: sum += float(thing)
print "The sum is", sum
def uppercaseCommand(*args):
for thing in args:
print thing.upper(),
print
def quitCommand(*args):
print "Goodbye!"
sys.exit(0)
def helpCommand(*args):
print "Here are your available commands: "
for key in DISPATCH_TABLE.keys():
description, function = DISPATCH_TABLE[key]
print "\t%s: %s" % (key, description)
"""Our dispatch table has function names as the keys, with
(description, function) tuples as values."""
DISPATCH_TABLE = { 'add' : ('Add numbers together.', addCommand),
'uc' : ('Uppercase arguments.', uppercaseCommand),
'quit' : ('Quit.', quitCommand),
'help' : ('You are looking at it.', helpCommand) }
def evaluate(command_line):
try:
function_name, arguments = (command_line.split()[0],
command_line.split()[1:])
if DISPATCH_TABLE.has_key(function_name):
description, function = DISPATCH_TABLE[function_name]
function(*arguments)
else:
print "I don't know about '%s'." % function_name
print "Try typing 'help' at the prompt.\n"
except SystemExit:
raise SystemExit
except (Exception), e:
print "Ooops: %s" % e
if __name__ == "__main__" :
while 1:
sys.stdout.write("Command me >>> ")
sys.stdout.flush()
try:
line = raw_input()
except EOFError:
evaluate("quit")
if line: evaluate(line)
###
And a sample run:
###
[dyoo@tesuque dyoo]$ python dispatcher.py
Command me >>> hello
I don't know about 'hello'.
Try typing 'help' at the prompt.
Command me >>> help
Here are your available commands:
uc: Uppercase arguments
help: You are looking at it.
add: Add numbers together
quit: Quit
Command me >>> uc this is a test of the emergency broadcast system
THIS IS A TEST OF THE EMERGENCY BROADCAST SYSTEM
Command me >>> add 3 4 5 6 7
The sum is 25.0
Command me >>> add three one four one five nine two six
Ooops: invalid literal for float(): three
Command me >>> quit
Goodbye!
###