[Tutor] Numbers & Characters As Dictionary Keys

Brian van den Broek bvande at po-box.mcgill.ca
Mon Jun 20 08:06:11 CEST 2005


DC Parris said unto the world upon 20/06/2005 01:13:
> I have a dictionary called Menu_Main:
> 
> Menu_Main =   { 1: ['People', Call_Fam],
>                 2: ['Groups', Call_Group],
>                 3: ['Events', nullfunc],
>                 4: ['Attendance', nullfunc],
>                 5: ['Visitation', nullfunc],
>                 6: ['Finances', nullfunc],
>             7: ['Administration', nullfunc],
>             10: ['Help', nullfunc],              # I would like to make the "10" an "h"
>             12: ['Quit', 'return']}               # and the "12" a "q".
> 
 >
 > I assume the keys can be of mixed types.  However, I'm not sure how
 > to adjust my code below that actually drives the menu system.  I
 > changed "input" to "raw_input", but I get "H is not defined" when I
 > run the script.  Essentially, I'd like the user to enter a number
 > for most items, but use letters for "Help", "Quit", and "Back to
 > Main".

> 
> def RunMenu(MenuList):
>     '''This is the function that drives the menu system.
> 
>     We place the "clear screen" command twice to provide a fresh screen for
>     each menu level.  We then call the menus above to display them.  There is a
>     special value for MenuList[sel][1] of 'return' which is the exit condition
>     for the loop. look at the entry for 9 of Menu_Main, or item 8 of Menu_Fam.
>     '''
>     while True:
>         for opts in MenuList.keys():            # print menu list
>             print opts, ': ', MenuList[opts][0] #
>         sel = input('Enter Selection:')  # get input
>         if sel in MenuList.keys():  #verify user input is a valid key
>             if MenuList[sel][1] == 'return': return MenuList[sel][0]
>             else: MenuList[sel][1]()
> 
> Thanks,
> Don


Hi Don,

you are better off using raw_input for reasons of security -- input 
executes the input it receives, which can be dangerous.

I'd probably just go with all dict keys being strings, be they '1', 
'h', or whatever. If you're set on some being ints rather than 
strings, here's one approach. (I've simplified the rest of the case to 
show the idea more clearly. Doubtless someone else could improve upon it.)

menu_dict = {1:'Action 1!', 2:'Action 2!', 'h':'Assistance here', 
'q':'For quitters'}

while True:
     # Sorted, as else there is no standard order for the keys.
     # Needs a reasonably recent Python -- I forget when it came in.
     # And, you can just print key in a_dict, you don't need
     # a_dict.keys()
     for key in sorted(menu_dict):
         print key, menu_dict[key]

     choice = raw_input('make your choice')
     try:
         choice = int(choice)
     except ValueError:
	# The ValueError will get raised for cases where choice is a
         # string not convertible into an int ('h', 'five', etc)
         pass
     if choice in menu_dict:
         print menu_dict[choice]
         break
     else:
         print "Please read the menu"

HTH,

Brian vdB



More information about the Tutor mailing list