A four-item text-based menu in Python I picked up python again, and I am proud with what I have without using if/elif statements throughout the whole thing. I have modified this couple of times, since I kept asking how could I make it better or more organized. My biggest complaint is using the if/elif at the bottom, for some reason when I use.

func = optionMenu.get(test, "INVALID ENTRY")


it would would return blank instead of showing "invalid entry" if I selected option that wasn't on the menu. So, I had to use if/else to band-aid it for now.

#!/usr/bin/env python

import os



def mainMenu():

    print "=" * 25
    print "Please Select An Option"
    print "=" * 25
    print ""
    print "1. option one\n"
    print "2. option two\n"
    print "3. option three\n"
    print "4. filler\n"
    menuOption = input("Select Option: ")

    optionSelect(menuOption)

class selections(object):
    def one(self):
        print "option one"

    def two(self):
        print "option two"

    def three(self):
        print "option three"

    def four(self):
        print "option four"

def optionSelect(test):
    menuSelection = selections()
    optionMenu = { 
    1 : menuSelection.one, 
    2 : menuSelection.two, 
    3 : menuSelection.three, 
    4 : menuSelection.four,
    }

    func = optionMenu.get(test)
    if test in optionMenu:
        func()
    else:
        print "ERROR INVALID ENTRY ERROR"
mainMenu()
I think, there is room for some improvement:

1) You are mixing OOP with procedural code

If you choose one paradigm, you should stick with it. Besides: why are you abstracting selections into a class and not the whole menu?

2) DRY - Don't repeat yourself

print "=" * 25
print "Please Select An Option"
print "=" * 25


Why are you repeating the same task? You could refactor the "=" * 25 into a constant: separator = "=" * 25.

Everytime you need a separator, you could use separator, which is more meaningful.

3) You should separate concerns

print "4. filler\n"
menuOption = input("Select Option: ")


Here you are mixing two concerns printing the options and prompting for input. This pollutes your mainMenu. One function should only do one thing (SRP).

4) Your code lacks an overall structure

If you take every point together, this should now be clear.



I came up with the following:

#!/usr/bin/env python2

import os
from collections import namedtuple

class Menu():

    Option = namedtuple('Option', 'label')
    _separator = "=" * 25
    _options = {1: Option("option one"), 2: Option("option two"),
                3: Option("option three"), 4: Option("option four")}

    def print_header(self):
        print "{0}\n Please Select An Option\n{0}\n".format(self._separator)

    def print_mainMenu(self):
        self.print_header()
        for option in sorted(self._options.keys()):
            print "{0} {1}".format(option, self._options[option].label)

    def prompt(self):
        return input("Select Option: ")

    def handle_input(self, chosen_option):
        try:
            print self._options[chosen_option].label
        except KeyError:
            print "Wrong Option"


def main():
    menu = Menu()
    menu.print_mainMenu()
    menu.handle_input(menu.prompt())

if __name__ == '__main__':
    main()


For this example, the use of namedtuple is not necessary, but on the other hand gives you something like a lightweight object which could not only contain lables. On top options[chosen_option].label is very readable.