Tkinter error UnboundLocalError: local variable 'flag' referenced before assignment
Question: I am trying to build quiz using tkinter and python 2

I am having trouble with maintaining score. The validate button can be pressed
multiple times which increments global score counter. 1) I've one flag
variable which will allow to answer only once and increment global counter
only once. Is it possible to disable validate button for correctly answered
question? But I'm getting error with it.

    
    
    Exception in Tkinter callback
    Traceback (most recent call last):
      File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1489, in __call__
        return self.func(*args)
      File "testtest.py", line 22, in validate
        if(q=="4" and flag==0):
    UnboundLocalError: local variable 'flag' referenced before assignment
    

**I read other answers for this problem** but if I pass arguments to validate
function it gives error.

2)Is there any way to implement quiz as it will display 1st question and if
answer is correct button event will direct to 2nd question unlike my code. It
displays all the questions  
My code is:

    
    
    import Tkinter as tk
    import tkMessageBox
    count=0
    
    class Question(tk.Frame):
        def __init__(self, *args, **kwargs):
                tk.Frame.__init__(self, *args, **kwargs)
        def show(self):
                self.lift()
    
    class Question1(Question):
        def __init__(self, *args, **kwargs):
                Question.__init__(self, *args, **kwargs)
                label = tk.Label(self, text="Question 1: What is 2^2")
                label.pack(side="top", fill="both", expand=True)
                entry = tk.Entry(self)
                entry.pack(side="top", fill="both", expand=True)
                def validate( event ):
                    q=entry.get()
    
                    if(q=="4" and flag==0):
                        tkMessageBox.showinfo('Correct Answer', 'Proceed to next question')
                        global count
                        count=count+1
                        fp=open("scores.txt","a")
                        fp.write("\nScore after Question 1 :%d "%(count)) 
                        flag=1
                    else:
                        tkMessageBox.showinfo('Wrong Answer', 'Try Again')
                        #flag=0  to avoid alternate event 
    
                button_1 = tk.Button(self, text="Validate")
                flag=0
                button_1.bind("<Button-1>", validate)
    
                button_1.pack(side="top", fill="both", expand=True)
    
    class Question2(Question):
    
        def __init__(self, *args, **kwargs):
                Question.__init__(self, *args, **kwargs)
                label = tk.Label(self, text="Question 1: What is 2^3")
                label.pack(side="top", fill="both", expand=True)
                entry = tk.Entry(self)
                entry.pack(side="top", fill="both", expand=True)
    
                def validate( event ):
                    q=entry.get()
    
                    if(q=="8" and flag==0):
    
                        tkMessageBox.showinfo('Correct Answer', 'Proceed to next question')
                        global count
    
                        count=0
                        count=count+1
    
    
                        fp=open("scores.txt","a")
                        fp.write("\nScore after Question 2 :%d "%(count)) 
                        flag=1
    
    
                    else:
                        tkMessageBox.showinfo('Wrong Answer', 'Try Again')
    
                button_1 = tk.Button(self, text="Validate")
                flag=0
                button_1.bind("<Button-1>", validate)
                button_1.pack(side="top", fill="both", expand=True)
    
    
    class MainView(tk.Frame):
        def __init__(self, *args, **kwargs):
                tk.Frame.__init__(self, *args, **kwargs)
                p1 = Question1(self)
                p2 = Question2(self)
    
                buttonframe = tk.Frame(self)
                container = tk.Frame(self)
                buttonframe.pack(side="top", fill="x", expand=False)
                container.pack(side="top", fill="both", expand=True)
    
                p1.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
                p2.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
    
    
                b1 = tk.Button(buttonframe, text="Question 1", command=p1.lift)
                b2 = tk.Button(buttonframe, text="Question 2", command=p2.lift)
    
    
                b1.pack(side="left")
                b2.pack(side="left")
    
    
                p1.show()
    
    if __name__ == "__main__":
        root = tk.Tk()
        main = MainView(root)
        main.pack(side="top", fill="both", expand=True)
        root.wm_geometry("1080x720")
        root.mainloop()
    


Answer: If you assign to a name in a function, it becomes a local name, even if the
function is nested in another function's scope that provides a definition. In
Python 3, you could explicitly declare `nonlocal flag` at the top of your
`validate` function to make it operate on `flag` from the nested scope, but in
Python 2, you can't; Python 2 only has `global` for this purpose, which would
skip the nested scope and look for `flag` at the top level scope of the
module; usually a bad idea for cases like this.

One approach is to use a `list` so you're assigning to an index, rather than
overwriting a local name.

    
    
    class Question1(Question):
        def __init__(self, *args, **kwargs):
            Question.__init__(self, *args, **kwargs)
            label = tk.Label(self, text="Question 1: What is 2^2")
            label.pack(side="top", fill="both", expand=True)
            entry = tk.Entry(self)
            entry.pack(side="top", fill="both", expand=True)
            flag = [0]  # Use list over plain int so you can index
            def validate( event ):
                q=entry.get()
    
                if q == "4" and not flag[0]:  # Test index of list
                    tkMessageBox.showinfo('Correct Answer', 'Proceed to next question')
                    global count
                    count=count+1
                    with open("scores.txt","a") as fp:
                        fp.write("\nScore after Question 1 :%d "%(count)) 
                    flag[0] = 1  # Assign to index of list
                else:
                    tkMessageBox.showinfo('Wrong Answer', 'Try Again')
                    flag[0] = 0  # Assign to index of list
    
            button_1 = tk.Button(self, text="Validate")
            button_1.bind("<Button-1>", validate)
    
            button_1.pack(side="top", fill="both", expand=True)
    

You'd need to make similar edits to `Question2` as well.

Note: I also changed you to using a `with` statement for the file
manipulation, so the file is closed and the data is written to disk at a
predictable time.

