Anyone familiar with wxPython? (increment number upon pressing button)

I began learning the Python language only 2 days ago, so there is surely much for me to learn. Still I’ve done a fair amount of studying and gotten up to writing code using wxPython.

I’m currently trying to write a program to simulate a simple Calculator. It’s just an experiment to see if I can do it. I’ve hit a snag though as my program relies upon a count being initiated once the user clicks on a button. I’m currently working on a much smaller code; if I can make this code work I’ll be able to figure out how to make my real code work.

Here is the sample code (keep in mind that I’d typically have everything indented properly; can’t do it here for some reason)
import wx
class Action(wx.Frame):
def init(self,parent,id):
wx.Frame.init(self,parent,id,‘Frame’,size=(750,600))
global panel
panel=wx.Panel(self)
**
self.Button2=wx.Button(panel,label=“Attempt”,pos=(130,200),size=(60,60))
self.Bind(wx.EVT_BUTTON,self.Attempt,self.Button2)

   count = 0

   def Attempt(self,event):
          count = count + 1
       
   if (count == 1):
       print("Program works")
    **

if name==‘main’:
app=wx.PySimpleApp() #This runs program
frame=Action(parent=None,id=-1) # Displays the program
frame.Show() # Show the frame
app.MainLoop() # Run the application
The important part of the code is put in bold. The point here is trying to print the message “Program works” as to indicate that the count has incremented due to the event associated with clicking the Attempt button. I get an error message saying :
" count = count + 1
UnboundLocalError: local variable ‘count’ referenced before assignment"

Again if I can somehow associate a number being incremented due to the use of a button than my real program should work. I’d need to access that number as global variables. So, does anyone have any suggestions?

The “count” in Attempt() is referring to the local variable.
You need to add

global count;

before operating on count

Stack overflow is a great resource:

You indent code by wrapping it in [code]code tags[/code] like this:



def fac(n):
   if n <= 1:
      return n
   else:
      return n * fac(n-1)


To preserve your code’s formatting, put it in


 tags. It's kind of important with Python, since without proper indentation your code is ambiguous.  :) I had to 'quote' your post to see how you had done the spacing originally:



import wx

class Action(wx.Frame):
def init(self,parent,id):
wx.Frame.init(self,parent,id,‘Frame’,size=(750,600))
global panel
panel=wx.Panel(self)

    self.Button2=wx.Button(panel,label="Attempt",pos=(130,200),size=(60,60))
    self.Bind(wx.EVT_BUTTON,self.Attempt,self.Button2)

count = 0

def Attempt(self,event):
    count = count + 1

if (count == 1):
    print("Program works")

if name==‘main’:
app=wx.PySimpleApp() #This runs program
frame=Action(parent=None,id=-1) # Displays the program
frame.Show() # Show the frame
app.MainLoop() # Run the application



If this is the intended formatting, then the problem is exactly what is being reported: *count* within the Attempt function is assumed to be a reference to a *local variable* -- because it hasn't been declared with *global* -- and since *count* hasn't been defined as a local variable yet, using it in an expression ('count + 1') is an error.

But note that declaring *global count* inside Attempt will not work either: there is no global variable named *count*.

What happened is this: when you put the code "count = 0" directly in the body of the class definition, what you did was create a *class variable* -- a variable whose value will be shared by all instances of the class. In other words, no matter how many instances of Action you create, they will all share a common count.

From here, it would really help to know your precise intent. Should all Action instances share a counter, or does it make more sense for each Action to have its own count?

If *count* should be a shared variable, then you can refer to it as *Action.count*, like this:



def Attempt(self, event):
    Action.count += 1



Otherwise, you need to make it an *instance variable* -- that is, make it a property of *self*. To do this, make sure you initialize it in the __init__ method:



def __init__(self, parent, id):
    self.count = 0

def Attempt(self, event):
    self.count += 1


Another question: when are you expecting that "if count == 1" statement to be executed? As it is, it will be executed *only once ever*, when the class declaration is executed -- meaning that "Program works" will never be printed, unless you change "count = 0" to "count = 1".

To get to the heart of the matter, it helps to understand how class definitions work in Python. Essentially, they are compound statements: when a class definition is executed, all the statements "inside" the definition are executed also, within a new local namespace. After the class definition has been executed, that namespace contains all the functions and class variables you defined -- and it is then bound to the specified class name by means of a "class object," which also includes inheritance information.