Python Class: Global/Local variable name not defin

2019-09-02 03:58发布

问题:

I have two sets of code, one which I use 'Class' (Second piece of code) to manage my code, and the other I just define functions, in my second piece of code I get a NameError: global name '...' is not defined. Both pieces of code are are for the same purpose.

from Tkinter import *
import ttk
import csv

USER_LOGIN = "user_login.csv"

class Login:
    def __init__(self, master):
        frame = Frame(master)
        frame.pack()

        lment1 = StringVar()
        lment2 = StringVar()


        self.usernameLabel = Label(frame, text="Username:")
        self.usernameLabel.grid(row=0, sticky=E)
        self.passwordLabel = Label(frame, text="Password:")
        self.passwordLabel.grid(row=1, sticky=E)

        self.usernameEntry = Entry(frame, textvariable=lment1)
        self.usernameEntry.grid(row=0, column=1)
        self.passwordEntry = Entry(frame, textvariable=lment2)
        self.passwordEntry.grid(row=1, column=1)

        self.loginButton = ttk.Button(frame, text="Login",   command=self.login_try)
        self.loginButton.grid(row=2)

        self.cancelButton = ttk.Button(frame, text="Cancel", command=frame.quit)
        self.cancelButton.grid(row=2, column=1)

    def login_try(self):
        ltext1 = lment1.get()
        ltext2 = lment2.get()
        if in_csv(USER_LOGIN, [ltext1, ltext2]):
            login_success()
        else:
            login_failed()

    def in_csv(fname, row, **kwargs):
        with open(fname) as inf:
            incsv = csv.reader(inf, **kwargs)
            return any(r == row for r in incsv)

    def login_success():
        print 'Login successful'
        tkMessageBox.showwarning(title="Login successful", message="Welcome back")

    def login_failed():
        print 'Failed to login'
        tkMessageBox.showwarning(title="Failed login", message="You have entered an invalid Username or Password")



root = Tk()
root.geometry("200x70")
root.title("title")
app = Login(root)
root.mainloop()

That is the second piece of code ^^^

# **** Import modules ****

import csv
from Tkinter import *
import ttk
import tkMessageBox

# **** Declare Classes ****

lGUI = Tk()
lment1 = StringVar()
lment2 = StringVar()
USER_LOGIN = "user_login.csv"

def in_csv(fname, row, **kwargs):
     with open(fname) as inf:
         incsv = csv.reader(inf, **kwargs)
         return any(r==row for r in incsv)


def login_try():
     ltext1 = lment1.get()
     ltext2 = lment2.get()
     if in_csv(USER_LOGIN, [ltext1, ltext2]):
        login_success()
     else:
        login_failed()


def login_success():
    print 'Login successful'
    tkMessageBox.showwarning(title="Login successful", message="Welcome back")


def login_failed():
     print 'Failed to login'
     tkMessageBox.showwarning(title="Failed login", message="You have entered an invalid Username or Password")


lGUI.geometry('200x100+500+300')
lGUI.title('PVH')


lButton = Button(lGUI, text="Login", command=login_try)
lButton.grid(row=3)

label_1 = Label(lGUI, text="Username")
label_2 = Label(lGUI, text="Password")
entry_1 = Entry(lGUI, textvariable=lment1)
entry_2 = Entry(lGUI, textvariable=lment2)

label_1.grid(row=0)
label_2.grid(row=1)

entry_1.grid(row=0, column=1)
entry_2.grid(row=1, column=1)

lGUI.mainloop()

And that is the piece of code that works^

I get the error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
    return self.func(*args)
  File "C:/Users/User/Desktop/PVH_work/PVH_program/blu.py", line 33, in login_try
    ltext1 = lment1.get()
NameError: global name 'lment1' is not defined

Any help would be appreciated :D

回答1:

In your first code piece, you define the variable 'lment1' in the __init __ method, making it local to that single method. When you then try to access the same variable in the 'login_try', Python doesn't know what it is.

If you wish to access the variable form wherever in the class, you should define it on the class level, by setting it on 'self'

def __init__(self, master):
    [...]
    self.lment1 = StringVar()
    [...]

That way, you can access it later with:

def login_try(self):
    [...]
    ltext1 = self.lment1.get()
    [...]

The reason it works in your second code sample, is because you defined it outside of any class - Making it globally available