0

im trying to do a menu. I have a validation to don´t accept string input. If the value ins numeric the function goes well but when the input is a string, something go wrong

def menudos(diccionario, titulo):
    os.system('clear')
    list_menu = []
    if diccionario:
        print(titulo)
        for key in diccionario:
            list_menu.append(key)
        list_menu.append("Volver")
        for x in range(0, len(list_menu)):
            print(x, ": ", list_menu[x])
        try:
            opcion = int(input("Seleccionar> "))
        except:
            menudos(diccionario, titulo)
        return list_menu[opcion]

The error is that:

Traceback (most recent call last):
  File "menudos.py", line 23, in <module>
    print(menudos(a, "Prueba"))
  File "menudos.py", line 21, in menudos
    return list_menu[opcion]
UnboundLocalError: local variable 'opcion' referenced before assignment

Thanks

2 Answers2

0

The problem is that when you provide not an int, the program raises the exception trying to convert non-int to int and nothing is assigned to your var opcion. If you want to protect your program from crashing. Execute try..except statement in an infinite loop waiting for the correct format of the index.

  • Btw providing non-int as a list index is an error by itself. If you want to have non-int indexed container use a dictionary. – Dawid Paluszkiewicz May 03 '19 at 20:24
  • That was i do in first place, and works propertly, i glad to don´t have many "Wrong answers" i prefer clean menu, but if it isn't posible, i think i gonna use an infinite loop. Thanks – Luis De Ambrosio May 03 '19 at 21:07
0

The specific traceback is caused because opcion is not defined in the except block, but you are trying to return list_menu[opcion] after going through the except block.

Instead, I would suggest that you use a while loop that will run forever until you get acceptable input from the user.

My approach to user menus has always been to separate the printing of the menu options and capturing the user input.

Something like:

def print_menu():
    print("Please make a selection:")
    print("1. Do item #1")
    print("2. Do item #2")
    # ...etc....

def get_user_input():
    selection = None
    while selection is None:
        try:
            selection = int(input("Selection: "))
            return selection
        except:
            print("You selected an invalid choice. Please choose again.")
            print_menu()

Hope this helps!

Edit: Also see this question on recursion in Python. There is a limit of 1000 recursive calls by default in Python - so, assuming your existing code worked, a user could enter 1000 incorrect entries and break your program.

David00
  • 133
  • 10
  • Also remember to check that your selection is a valid index (user shall not be able to select 9 if there is only 3 options) –  May 03 '19 at 20:29
  • Hi, thanks for answered me. The problem of do in your way is that i want a function wich i can use in several dict. So un parameter of the func must be a dictionary... – Luis De Ambrosio May 03 '19 at 21:04