0

I've just started programming in Python and I'm getting x is not defined but I have no idea why it is saying that considering I think it is defined.

def menu():
    x = 0
    while x != 1 or 2:
        print "menu"
        print "1)login"
        print "2)under dev"
        x = raw_input('select menu option')
        if x == 1 or 2:
            break
menu()
if x=='1':
    print "enter username:"
y = raw_input()
if y=="username":
    print "enter password:"
z = raw_input()
if z=="password":
    print "password accepted"
elif x=='2':
    print "under development"
elif y or z == False:
    print "username or password incorrect"
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
Tyler Lund
  • 13
  • 1
  • 4
  • `elif y or z == False:` not correct, this will check `if y` or `if z == False` you want `if y == False or z == False` – Inbar Rose Mar 17 '13 at 14:39

4 Answers4

6

x is a local variable in the menu() function, it doesn't exist outside of menu().

You could return it from menu() then store the value in a new x in your code:

def menu():
    x = None
    while x not in ('1', '2'):
        print "menu"
        print "1)login"
        print "2)under dev"
        x = raw_input('select menu option')
    return x

x = menu()

Note that I fixed several problems with your code in menu() as well.

  • raw_input() returns a string, but you test if x is integer 1 or 2 instead. I changed the code to test for the strings '1' and '2' instead.

  • Don't use x != 1 or 2, that does not mean what you think it means. It tests if x != 1 is True, and if not, it tests if 2 is True. 2 is always True because all non-zero numbers are considered True in a boolean context.

    I replaced that with a x not in ('1', '2') test.

  • There is no need to test x inside the loop again and execute a break; the while loop will just exit on its own without that test.

  • It doesn't really matter what x is set to at the start of menu(), as long as it is not '1' or '2'. None is a good choice to signal that it is 'empty'.

Jon Clements
  • 138,671
  • 33
  • 247
  • 280
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
0

The variable x is defined in the menu function. It is this a local variable, and only accessible from the body of the function. This answer has good explanation of Python scoping rules.

Community
  • 1
  • 1
Sylvain Defresne
  • 42,429
  • 12
  • 75
  • 85
0

If you are still confused about using global and local variables, look at this website.

erdekhayser
  • 6,537
  • 2
  • 37
  • 69
0

Your Problem is because of Python's scopes
which are stated here (and below):
LEGB Rule.

  • Local.
    Names assigned in any way within a function, and not declared global in that function.
  • Enclosing function locals.
    Name in the local scope of any and all enclosing functions (def or lambda), form inner to outer.
  • Global (module).
    Names assigned at the top-level of a module file, or declared global in a def within the file.
  • Built-in (Python).
    Names preassigned in the built-in names module : open, range, SyntaxError, etc

So, your x variable is a variable local to main(). So, to get the variable out of the local scope, you can get the global variable to the local scope too.

Your code seems to have various logical errors (and some NameErrors). I've tried to understand and have changed/reformed your code, to something that will work.

def menu():
    global x
    while x not in ('1','2'): # 1
        print "   Menu"
        print "1) Login"
        print "2) Under dev"
        x = raw_input('Select menu option: ') # 2
        if x in ('1','2'): # 1
            break
x = ''
menu()
# 3
if x == '1':
    y = raw_input("enter username: ") # 2
    z = raw_input("enter password: ") # 2
    if y != 'username' or z != 'password': # 4
        print "username or password incorrect"
    else: # 5
        print 'You will be logged in'
elif x == '2':
    print "Under development"

Other than the grammatical changes, lets see the changes on the logical part.(The numbers in comments refer to the point which elaborates on the change.)

  1. raw_input returns a string. So, it will never be 1 or 2 (integers).
    Also, x != 1 or 2 will evaluate to True as it is equivalent to (x != 1) or (2) and 2 always has a True value in Python.
  2. raw_input takes a prompt as an argument, which is displayed before taking the input from
  3. Simply put, the structure of your ifs and elifs is not correct.
  4. y or z == False is evaluated to (y) or (z = False) And z is never False as it is a string.
    So, if y is not '', then this is evaluated to True, but that is not like something you want (it seems)..
  5. The code in else is executed if the if (and all the elifs) conditionals are False.
    Here we give the under development message.

More coming

Community
  • 1
  • 1
pradyunsg
  • 18,287
  • 11
  • 43
  • 96