What is the best way to perform a menu with submenus ( while with breaks or calling the menus in functions )?

Asked

Viewed 5,595 times

1

For a school project I need to have a menu with several submenus. What is the best way to approach this? I can put the menus inside whiles and give away break to those whiles when you want to go back to the previous one or separate the menus in functions and go calling when needed.

I do not know what would be the best option, I am open to suggestions, thanks in advance. for example

while 1:

# menu principal
existe()
print("========================")
print("     SA Airlines    ")
print("========================")
print("[1] - Adicionar")
print("[2] - Listar")
print("[3] - Procurar")
print(" ")
res = int(input("Opcao: "))

if res == 1:
    add.adicionar()
elif res == 2:

    while 1:

        # um menu secundario
        print("[1] - Aeronaves")
        print("[2] - Aeroportos")
        print("[3] - Rotas")
        print("[4] - Voltar")

        res = int(input("Opcao: "))
        if res == 1:
            listar.mostraAeronaves()
        elif res == 2:
            listar.mostraAeroportos()
        elif res == 3:
            listar.mostraRotas()
        elif res == 4:
            break;
        else:
            print("ERRO: A opção não se encontra defenida ! tente novamente!")
  • 3

    You should also put what you have and/or an example of the final result you want. You can edit here: http://answall.com/posts/172820/edit

  • I’ve already posted the code I have, I think from here I can get an idea of what I was trying to do

  • Hello SKL13D, one option is to have dictionaries representing each level menu. The value of each key is either a function (which you can call for) or another dictionary (representing another level of menus).

  • Do you need the while there? Why?

  • it was to re-display the menu until the user wants to go back to the previous one or leave the program anyway, but I think with the hint that Anthony gave I can put the menu right, I’ll see.

  • Use functions. Imagine that the function does not need to know where it was called - Panneas displays its options and returns the response. And then you realize that you don’t need to have any difference of functions that display sub-menus and those that effectively do things of the system.

Show 1 more comment

1 answer

2


When they invented programming functions, it’s because they’re MUCH BETTER to organize the program and its contents - and this includes organizing the menu structure: you should not think that only the functionalities at the tips should be functions and that any code in the main body, either way, serves to do the menus.

If the menus all behave in the same way: have to display a list of options, pick a number and perform something else based on that number, the best thing you do is create a generic function to display these menus and the answer - and then you get the whole structure pre of the program very short and separate from the main logic:

aeronaves = []
aeroportos = []


def menu(titulo, opcoes):
    while True:
        print("=" * len(titulo), titulo, "=" * len(titulo), sep="\n")
        for i, (opcao, funcao) in enumerate(opcoes, 1):
            print("[{}] - {}".format(i, opcao))
        print("[{}] - Retornar/Sair".format(i+1))
        op = input("Opção: ")
        if op.isdigit():
            if int(op) == i + 1:
                # Encerra este menu e retorna a função anterior
                break
            if int(op) < len(opcoes):
                # Chama a função do menu:
                opcoes[int(op) - 1][1]()
                continue
        print("Opção inválida. \n\n")

def principal():
    opcoes = [
        ("Adicionar", adicionar),
        ("Listar", listar),
        ("Procurar", procurar)
    ]
    return menu("SA AIRLINES", opcoes)

def adicionar():
    opcoes = [
        ("Aeronaves", adicionar_aeronave),
        ("Aeroportos", adicionar_aeroporto),
        # ...
    ]
    return menu("Adicionar", opcoes)

def adicionar_aeronave():
    aeronaves.append(input("Nova aeronave: "))


def adicionar_aeroporto():
    aeroportos.append(input("Nova aeronave: "))

    #...

def listar():
   ...

def procurar():
   ...

principal()

I used an important feature of Python which is the possibility to pass functions as normal objects - that is, the "menu" function receives the functions themselves that should call, in each option, with parameters - and calls the appropriate functions in the line opcoes[int(op) - 1][1]().

The functions that use the menu define the options as a sequence of items with two other internal items: the first is the printable name of the option, and the second is the function itself, as an object. For this just put the name of the function without adding the ( ) that characterize the function call. (Otherwise Python simply calls the function unconditionally at that point and adds the value returned by it in the list of options)

Thus, the line opcoes[int(op) - 1][1]() "says" in item "op - 1" of the options , take the second item - which is the function itself (this we declare within the various functions that declare options to call the menu) and call this object as a function, without parameters.

Note that doing so, if tomorrow you decide to add a graphical interface for example instead of using prints and inputs, just redo the "menu" function and the whole structure of the program continues working normally.

  • 1

    Notice that the code you posted, made me learn many things I didn’t know, and that are really useful ! and I am grateful for your willingness to teach me this ( mainly that technique of calling the functions, which will help me a lot, since I am "beginner to python"). I must also point out that in this part of the code if int(op) == i: should be if int(op) == i+1: because the i would only go from 1 to X (X being the size of the list), and the return/exit option would be a value in front of i as it was in the format(i+1),

  • That said, thank you !

  • Nice that you found my mistake. For me it’s important because it means that you understand the idea. (I’ll fix it now).

  • I’ve been back from this but I haven’t had time to finish. It’s good +1, a question, you couldn’t call funcao() since you are unpacking in the for cycle? Instead of opcoes[int(op) - 1][1]()?

  • The function object is accessed in opcoes[int(op) - 1][1] - And once you have reference to it, you can call it, simply put the parentheses. Nothing prevents you from referencing that same object in another variable one or a few lines above - (and this variable can be called "function") -and in this case funcao() would make exactly the same call, yes. In the above code, however, the "function" variable points to each menu option only inside the loop for - outside it, where the user option is used, funcao always points to the last function of the list of options.

  • Of course I do, my distraction, I didn’t notice that you had already left the room when you use it. Sorry jsbueno

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.