I've been learning python and I'm almost finished and I'm learning about oop. I have a question, is it possible to make a looping menu using oop on python (Not using Tkinter, WX) without having to key in the object. I learn better through playing around with what I've learned after I finished a lesson.

I was thinking of something similar to this this program.

main='a ,b ,c , exit,'
menua='apples, Amanda, alphabet, main menu, back, exit '
menub='banana, Betty, beagle, main menu, back, exit '
menuc='chocolate, Cleo, cats, main menu, back, exit '
submenua='green apples, red apples, main menu, back, exit '
submenuc='porkchop, guera, scooter, houdini, main menu, back, exit '
exit='leave'
def m():


    while True:
            choice=raw_input("Select one of the options: {} \n".format(main))
            choice=choice.lower()
            if choice=="a":
                    a()
            elif choice=="b":
                    b()
            elif choice=="c":
                    c()
            elif choice=="exit":
                    break


def a():
        while True:
                choice=raw_input("Select one of the options: {}\n ".format(menua))
                choice=choice.lower()
                if choice=="apples":
                        suba()
                elif choice=="amanda":
                        print"My friend Jinxy\n "
                elif choice=="alphabet":
                        print"The letters from A to Z\n "
                elif choice=="main menu":
                        m()
                elif choice=="exit":
                        leave()
                elif choice=="back":
                        break


def suba():
        while True:
                choice=raw_input("Select one of the options: {}\n".format(submenua))
                choice=choice.lower()
                if choice in ("red apples, red apple"):
                        print"You like red apples\n "
                elif choice in("green apples, green apple"):
                        print"You like green apples\n "
                elif choice=="main menu":
                        m()
                elif choice=="back":
                        break
                elif choice=="exit":
                        leave()
                else:
                        print"Please select from one of the options\n"

def b():
        while True:
                choice=raw_input("Select one of the options: {}\n ".format(menub))
                choice=choice.lower()
                if choice=="banana":
                        print "banana's are delicious\n "
                elif choice=="betty":
                        print "Short for Elizabeth\n "
                elif choice=="beagle":
                        print "Snoopy is a beagle\n "
                elif choice=="main menu":
                        m()
                elif choice=='back':
                        break
                elif choice=="exit":
                       leave()
                else:
                        print"Select one of the options"

def c():
        while True:
                choice=raw_input("Select one of the options: {}\n ".format(menuc))
                choice=choice.lower()
                if choice=="chocolate\n":
                        print "I'm a chocoholic\n "
                elif choice=="cleo":
                        print "Short for Cleopatra\n "
                elif choice=="cats":
                        subc()
                elif choice=="main menu":
                        m()
                elif choice=="exit":
                        leave()

def subc():
        while True:
                choice=raw_input("Select one of the options: {}\n".format(submenuc))
                choice=choice.lower()
                if choice=="porkchop":
                        print"La Mona\n"
                elif choice=="guera":
                        print"La quoqueta\n"
                elif choice=="scooter":
                        print"Its fuzzy butt!!!\n"
                elif choice=="houdini":
                        print"The best escape artist\n "
                elif choice=="main menu":
                        m()
                elif choice=='back':
                        break
                elif choice=="exit":
                        leave()

def leave():
        while True:
                exit=raw_input("Are you sure you want to exit <yes,no>? \n")
                exit=exit.lower()
                if exit=="yes":
                        quit()
                elif exit=="no":
                        break
m()

You could start an OOP menu system like this for example

#!/usr/bin/env python
# -*-coding: utf8-*-
'''doc
'''
from __future__ import (absolute_import, division,
                        print_function, unicode_literals)

class Choice(object):
    def __init__(self, desc):
        self.desc = desc

    def on_selection(self, menu, index):
        print("'{}' was selected".format(self.desc))
        return self

class ExitChoice(Choice):
    def on_selection(self, menu, index):
        print("bye")
        raise SystemExit

class Menu(object):
    def __init__(self, question):
        self.question = question
        self.choices = []

    def add_choices(self, choices):
        self.choices.extend(choices)

    def input(self):
        choice_list = "\n".join("    {}) {}".format(i, x.desc) for i, x in enumerate(self.choices, 1))
        s = """{}\n{}\n""".format(self.question, choice_list)
        prompt = "? "
        while True:
            user = raw_input(s + prompt)
            try:
                c = int(user.strip())
                choice = self.choices[c-1]
            except (IndexError, ValueError):
                prompt = "ERROR: please input an integer in {}..{}\n? ".format(1, len(self.choices))
                continue
            return choice.on_selection(self, c-1)

def main():
    menu = Menu("Please select an item")
    menu.add_choices([
        Choice('porkchop'), Choice('guera'), Choice('scooter'),
        Choice('houdini'), ExitChoice('exit'),
    ])
    menu.input()

if __name__ == '__main__':
    main()

""" my output -->
Please select an item
    1) porkchop
    2) guera
    3) scooter
    4) houdini
    5) exit
? 4
'houdini' was selected
"""

Edit: improved

Edited 1 Year Ago by Gribouillis

I get more or less how you did it, but I wanted to make it entirely using oop. I remade the program using just oop but when I try and run it I keep getting the following error message.
"self.menus=[mainMenu(),menua(),menub(),menuc(),submenua(),submenuc()]
TypeError: 'list' object is not callable"
How is it not callable if I have it defined in the constructor and I have a method for each menu? This is what I have so far.

mainMenu=['main menu','a','b','c','d','exit']
menua=['menua','apples','Amanda','alphabet','main menu','exit']
menub=['menub','banana','Betty','beagle','main menu','exit']
menuc=['menuc','chocolate','Cleo','cats','main menu','exit']
submenua=['green apples','red apples','main menu','back','exit']
submenuc=['porkchop','guera','scooter','houdini','main menu','back','exit']


class letters(object):
    def __init__(self,menus,choice):
        self.menus=[mainMenu(),menua(),menub(),menuc(),submenua(),submenuc()]
        self.choice=choice

    def Main(self):
        print "Select one of the options: {}\n".format(self.menus(mainMenu))
        for i in range(len(mainMenu)):
            print mainMenu[i]
            if choice =="menua":
                return menua
            elif choice =="menub":
                return menub
            elif choice =="menuc":
                return menuc
            elif choice =="exit":
                quit
            else:
                return Main
    def a(self):
        print menua

    def b(self):
        print menub

    def c(self):
        print menuc

    def suba(self):
        print submenuc

    def subc(self):
        print submenuc

    def run(self):
        for s in self.Main:
            print s.enter() 

If mainMenu is a list, the expression mainMenu() does not make sense because mainMenu is not a function (it is not callable in python's terminology). The same holds for menua, menub etc.

Edited 1 Year Ago by Gribouillis

Right, right, duh I missed that in my haste to write the program. I have another question and I hope you can help me out with it. I've been learning python and I'm stuck on a lesson where I am suppose to create a game using oop (Which is why I tried to make that game I showed you using nothing but functions work into a oop program so I could get an idea what I was doing), I get how the whole thing works, but I cant wrap my head around the area where the program has a loop. I've tried to copy what other programmers have used to make their oop program work , but I can't seem to make mine work and I don't even know if I'm doing it correctly. Ive seen different programmers online use different methods to make it work, but I cant find a tutorial anywhere explaining how they came to that conclusion or samples of how to make it work. Would you be able to explain it to me using the program Ive been working on here in this website and please explain to me why you did that particular piece of code step by step?. The part I'm talking about is where I have the method with run in it.

Right, right, duh I missed that in my haste to write the program. I have another question and I hope you can help me out with it. I've been learning python and I'm stuck on a lesson where I am suppose to create a game using oop (Which is why I tried to make that game I showed you using nothing but functions work into a oop program so I could get an idea what I was doing), I get how the whole thing works, but I cant wrap my head around the area where the program has a loop. I've tried to copy what other programmers have used to make their oop program work , but I can't seem to make mine work and I don't even know if I'm doing it correctly. Ive seen different programmers online use different methods to make it work, but I cant find a tutorial anywhere explaining how they came to that conclusion or samples of how to make it work. Would you be able to explain it to me using the program Ive been working on here in this website and please explain to me why you did that particular piece of code step by step?. The part I'm talking about is where I have the method with run in it.

def run(self):
        for s in self.Main:
            print s.enter() 

I don't understand your program. The first thing to do is always to solve the error messages sent by the python interpreter itself. Can you post the current state of your program, if it executes without error ?

Sorry it took so long to get back, I've been busy. I kept it re did the whole program and kept it simple. I didn't want to bite off too much before I figured how to make the oop program loop and I figure once I get the program to loop I can work on making it menu driven program. I can run it and it doesn't show any error messages, I've scoured the Internet for samples of other programmers work and they all have different ways to do it, but I can't find any tutorial on how they did it or why they chose that way to do it. Below is my program.

class Letters(object):
    def __init__(self):
        self.Menus=None
        self.Choice=None
        self.Question=None

    def stuff(self,Menus,Choice,Main,Amenu,Bmenu,Cmenu,question):
        self.Menus={"MainMenu":MainMenu(),"MenuA":MenuA(),
                    "MenuB":MenuB(),"MenuC":MenuC()}#Different menus in program
        self.Choice=Choice#used as a prompt
        self.Main={"MenuA\n","Menub\n","Menuc\n","ExitMenu\n"}#Display string for Main menu
        self.Amenu={"Main menu\n","Menub\n","Menuc\n","ExitMenu\n"}#Display string for menu a
        self.Bmenu={"Main menu\n","Menua\n","Menuc\n","ExitMenu\n"}#Display string for menu b
        self.Cmenu={"Main menu\n","Menua\n","Menub\n","ExitMenu\n"}#Display string for menu c
        self.question=("Selection an option ")

class MenuMain(Letters):
    def enter(self):
        while True:
            choice=raw_input("Select one of the options: {}\n".format(Main))
            if choice=='MenuA':
                return "MenuA"
            elif choice=='MenuB':
                return "MenuB"
            elif choice=='MenuC':
                return "MenuC"
            else:
                print "Select one of the choices "

class MenuA(Letters):
    def enter(self):
        while True:
            choice=raw_input("Select one of the options: {}\n".format(Amenu))
            if choice=="MenuB":
                return "MenuB"
            elif choice=="MenuC":
                return "MenuC"
            elif choice=="Main Menu":
                return "MenuMmain"
            else:
                print "Select one of the options "

class MenuB(Letters):
    def enter(self):
        while True:
            choice=raw_input("Select one of the options: {}\n".format(Bmenu))
            if choice=="Main Menu":
                return "MenuMain"
            elif choice=="MenuA":
                return "MenuA"
            elif choice=="MenuC":
                return "MenuC"
            else:
                print "Select one of the options "

class MenuC(Letters):
    def enter(self):
        while True:
            choice=raw_input("Select one of the options: {}\n".format(Cmenu))
            if choice=="Main Menu":
                return "MenuMain"
            elif choice=="MenuA":
                return "MenuA"
            elif choice=="MenuB":
                return "MenuB"
            else:
                print "Select one of the options "

What I am trying to do is figure out lesson #43 of learn python the hard way. Zed wants us to make a game and I understand how oop works and how to make the game he wants me to create, but I can't figure out how he loops it from one class to another. SO I figured I'd take a step back and try and make my own looping oop menu similar to the one I made with functions so I could figure out how to do it. Ive seen different programmers use different ways to make it loop using a method and calling it 'run' or 'play'.

The key is in the Engine class

class Engine(object):

    def __init__(self, scene_map):
        self.scene_map = scene_map

    def play(self):
        current_scene = self.scene_map.opening_scene()
        last_scene = self.scene_map.next_scene('finished')

        while current_scene != last_scene:
            next_scene_name = current_scene.enter()
            current_scene = self.scene_map.next_scene(next_scene_name)

        # be sure to print out the last scene
        current_scene.enter()

The engine has a current_scene and the looping is done by changing the current scene. The current_scene is a state variable. In your your menu system, you can define an Engine class with a current menu. The current menu is displayed and depending on the user's choice, a new menu is chosen to become the current menu.

Think about a car. It always has a current position, now suppose that you drive the car from one town to another and in every town you display a menu asking: where should I go next ? Depending on the user's answer, you drive to another town and display a new menu.

Trying to simplify the program. I know many people try and make their program look fancy, so I tried to make it simpler and I figure the easier it is to read the easier it is to maneuver around it to correct or add things to it. I read your reply and I get how the current_scene is the variable and was changed.

This is what I have so far. I now get the following error messages.
line 82, in <module>Letters().run()
line 22, in run self.stuff()
TypeError: stuff() takes exactly 6 arguments (1 given)

class Letters(object):
    def __init__(self):
        self.Menus=None
        self.Choice=None
        self.Question=None
        self.MenuMain=None
        self.Amenu=None
        self.Bmenu=None
        self.Cmenu=None
        self.CurrentMenu=None

    def stuff(self,Menus,Amenu,Bmenu,Cmenu,CurrentMenu):
        self.Menus={"MainMenu":MainMenu(),"MenuA":MenuA(),
                    "MenuB":MenuB(),"MenuC":MenuC()}#Different menus in program
        self.Main={"MenuA\n","Menub\n","Menuc\n","ExitMenu\n"}#Display string for Main menu
        self.Amenu={"Main menu\n","Menub\n","Menuc\n","ExitMenu\n"}#Display string for menu a
        self.Bmenu={"Main menu\n","Menua\n","Menuc\n","ExitMenu\n"}#Display string for menu b
        self.Cmenu={"Main menu\n","Menua\n","Menub\n","ExitMenu\n"}#Display string for menu c
        self.CurrentMenu=MenuMain

    def run(self):
        self.stuff()
        while self.CurrentMenu:
            self.CurrentMenu()

class MainMenu(Letters):
    def enter(self):
        print "Select one of the options: {} ".format(Main)
        while True:
            choice=raw_input()
            if choice=='MenuA':
                return "MenuA"
            elif choice=='MenuB':
                return "MenuB"
            elif choice=='MenuC':
                return "MenuC"
            else:
                print "Select one of the choices "

class MenuA(Letters):
    def enter(self):
        print "Select one of the options: {} ".format(Amenu)
        while True:
            choice=raw_input()
            if choice=="MenuB":
                return "MenuB"
            elif choice=="MenuC":
                return "MenuC"
            elif choice=="Main Menu":
                return "MenuMmain"
            else:
                print "Select one of the options "

class MenuB(Letters):
    def enter(self):
        print "Select one of the options: {} ".format(Bmenu)
        while True:
            choice=raw_input()
            if choice=="Main Menu":
                return "MenuMain"
            elif choice=="MenuA":
                return "MenuA"
            elif choice=="MenuC":
                return "MenuC"
            else:
                print "Select one of the options "

class MenuC(Letters):
    def enter(self):
        print "Select one of the options: {} ".format(Cmenu)
        while True:
            choice=raw_input()
            if choice=="Main Menu":
                return "MenuMain"
            elif choice=="MenuA":
                return "MenuA"
            elif choice=="MenuB":
                return "MenuB"
            else:
                print "Select one of the options "

Letters().run()

I followed your advice, took a step back and realised I was making my program too complicated. I simplified it and now I have a new problem. When the options appear on the screen, anytime I select an option other than 'exit', it will dislay the choice and then any other letter, number, action will cause the program to scroll and not do anything. The only time it works is when I select 'exit'. This is what I have so far.

class Letters(object):
    def __init__(self):
        self.Menus={"MainMenu":MainMenu(),"MenuA":MenuA(),
                        "MenuB":MenuB(),"MenuC":MenuC()}#Different menus in program
    def run(self):
        start="MainMenu"
        while True:
            if start =="MainMenu":
                start = self.Menus.get(start).enter()

class Scene(object):

    def enter(self):
        pass
        exit(1)

class MainMenu(Scene):
    def enter(self):
        print "Select one of the options: \n1.MenuA\n2.MenuB\n3.Menuc\n4.exit "
        while True:
            choice=raw_input()
            choice=choice.lower()
            if choice=='1':
                return "MenuA"
            elif choice=='2':
                return "MenuB"
            elif choice=='3':
                return "MenuC"
            elif choice=="4":
                exit(1)
            else:
                print "Select one of the choices "
                return "MainMenu"

class MenuA(Scene):
    def enter(self):
        print "Select one of the options: \nMainmenu\nMenuB\nMenuC\nexit"
        while True:
            choice=raw_input()
            choice=choice.lower()
            if choice=="mainmenu":
                return "MainMenu"
            elif choice=="menub":
                return "MenuB"
            elif choice=="menuc":
                return "MenuC"
            elif choice=="exit":
                exit(1)
            else:
                print "Select one of the options "
                return "MenuA"
class MenuB(Scene):
    def enter(self):
        print "Select one of the options: \nMain Menu\nMenuA\nMenuC\nexit\n"
        while True:
            choice=raw_input()
            choice=choice.lower()
            if choice=="main menu":
                return "MenuMain"
            elif choice=="menua":
                return "MenuA"
            elif choice=="menuc":
                return "MenuC"
            elif choice=="exit":
                exit(1)
            else:
                print "Select one of the options "

class MenuC(Scene):
    def enter(self):
        print "Select one of the options: \nMainMenu\nMenuA\nMenuB\nexit\n"
        while True:
            choice=raw_input()
            choice=choice.lower()
            if choice=="main menu":
                return "MenuMain"
            elif choice=="menua":
                return "MenuA"
            elif choice=="menub":
                return "MenuB"
            elif choice=="exit":
                exit(1)
            else:
                print "Select one of the options "

Letters().run()

Remove the test in run()

    def run(self):
        start="MainMenu"
        while True:
            start = self.Menus.get(start).enter()

Also you could replace exit(1) with exit(0). A value of 0 means that the program exits normally (without error).

I looked over my program and searched online to see what you meant by remove the test from run(). Forgive my silly question but I am still learning python, but what did you mean by that?.

This article has been dead for over six months. Start a new discussion instead.