Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Solving a scope issue
#1
Hi all,

I'm fairly new to Python and have been able to develop a fair amount of code including some GUI (using wxPython for the GUI but believe this is a regular Python problem). My issue has to do with resolving scope.

I have a class definition with a whole bunch of stuff (defs, etc.) in it:

      class MainClassWindow(wx.Frame):
	    def __init__(self):
         ....lots of stuff snipped....  
In this class I created and bind-ed a togglebutton definition:
self.pwr_btn.Bind(wx.EVT_TOGGLEBUTTON, self.PWRToggle)

And also defined the callback/function:
     def self.PWRToggle(event):
	    if self.pwr_btn.GetValue() == True:
         ....not so much stuff snipped....  
The program runs fine with the pwr_btn functioning as expected. I decided to "module-ize" the PWRToggle callback (when I did that self.PWRToggle changed to PWRToggle both in the main class and callback module) and then import it (and plan to do the same with a bunch of other callbacks). As a module, the import part works fine, but now when I press pwr_btn I get the following error msg:

NameError: name 'self' is not defined
(Note: also changed self.pwr_btn to just pwr_btn and pwr_btn became the error)

I understand why I get the error (I have other objects like variables, labels, etc. that will also be accessed by the callback and expect the same errors). I believe I also understand how the code in my main class is able to see the callback...the callback, an imported module, is now global.

So, how do I solve the scope issue so that module-ized callbacks (and I'm creating a few more, as well) like this one can "see"/access objects back in class MainClassWindow? My guess is that I may need to pass some kind of object reference to the callback, but am unsure of the best way to do this. I also can't imagine "global"-ing a whole bunch of objects.

Thanks in advance for the help.....Cheers....
Reply
#2
The first problem is that
def self.spam(...):
    ...
is not valid python code. It should be
def spam(self, ...):
    ...
Reply
#3
@Larz60+ Apologies. I'll try to be better next time (see below :) Thx.

@Gribouillis

Appreciate the fast response.

I had already tried your suggestion and got the following error:

TypeError: PWRToggle() missing 1 required positional argument: 'event'
It seems "self" isn't being passed to def PWRToggle(self, event):

As I mentioned in my original posting, this is my button instantiation code:

self.pwr_btn.Bind(wx.EVT_TOGGLEBUTTON, PWRToggle)
Is there something I should be doing in this statement to fix this?

I also mentioned that I moved this code from within my main init def:

class MainClassWindow(wx.Frame):
    def __init__(self):
    ....lots of stuff snipped....  
to being an "import"-ed module which, I assume, makes it global.

Thanks for the help.....Cheers....

(Oct-20-2019, 07:00 AM)Gribouillis Wrote: The first problem is that
def self.spam(...):
    ...
is not valid python code. It should be
def spam(self, ...):
    ...
Reply
#4
(Oct-20-2019, 04:25 PM)profconn1 Wrote: It seems "self" isn't being passed to def PWRToggle(self, event):

That's because when you moved it out of the class and into another module, it stopped being a bound method. Now it's just a function. You could take that function and bind it to the class when it instantiates, but that gets rather deep into the Python internals. When I find myself doing that, I ask myself if there is another way around the problem.

If you need that function to be available to other classes, it would probably be best to make a class with that function as a method, and then subclass from that. So you would have the modularized form be:

class FunctionFrame(wx.Frame):
    def self.PWRToggle(event):
        if self.pwr_btn.GetValue() == True:
            ...
And then your main class would inherit from that:

  
from other_module import FunctionFrame

class MainClassWindow(FunctionFrame):
    def __init__(self):
        ...  
If you have some other reason to be modularizing that function, the solution would depend on that reason.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
I wanted to get back to you on this.

1st, I appreciate your response. It did help me better understand what I might want to do.

I may still go this route since I would like to divide my code into smaller, more manageable pieces (whatever that may mean :( However, I came across a "solution" that may be better, for the moment. I installed an outliner add on into SublimeText3. That offers me visibility (and easier access) to the classes and methods/functions I create. How that may work as my code continues to grow remains to be seen. Maybe that's when I come back to a more modular approach and figure out how to deal with objects.

What I can do now is put variables and other definitions into modules since most of those are accessed by most, or many, of my routines.

Thanks again for the help. I'll mark this thread solved for now.

(Oct-20-2019, 05:36 PM)ichabod801 Wrote:
(Oct-20-2019, 04:25 PM)profconn1 Wrote: It seems "self" isn't being passed to def PWRToggle(self, event):

That's because when you moved it out of the class and into another module, it stopped being a bound method. Now it's just a function. You could take that function and bind it to the class when it instantiates, but that gets rather deep into the Python internals. When I find myself doing that, I ask myself if there is another way around the problem.

If you need that function to be available to other classes, it would probably be best to make a class with that function as a method, and then subclass from that. So you would have the modularized form be:

class FunctionFrame(wx.Frame):
    def self.PWRToggle(event):
        if self.pwr_btn.GetValue() == True:
            ...
And then your main class would inherit from that:

  
from other_module import FunctionFrame

class MainClassWindow(FunctionFrame):
    def __init__(self):
        ...  
If you have some other reason to be modularizing that function, the solution would depend on that reason.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to create a variable only for use inside the scope of a while loop? Radical 10 1,524 Nov-07-2023, 09:49 AM
Last Post: buran
  Library scope mike_zah 2 796 Feb-23-2023, 12:20 AM
Last Post: mike_zah
  Scope of variable confusion Mark17 10 2,739 Feb-24-2022, 06:03 PM
Last Post: deanhystad
  Variable scope issue melvin13 2 1,507 Nov-29-2021, 08:26 PM
Last Post: melvin13
  Variable scope - "global x" didn't work... ptrivino 5 2,979 Dec-28-2020, 04:52 PM
Last Post: ptrivino
  Python Closures and Scope muzikman 2 1,775 Dec-14-2020, 11:21 PM
Last Post: muzikman
  Block of code, scope of variables and surprising exception arbiel 8 3,338 Apr-06-2020, 07:57 PM
Last Post: arbiel
  Help with Global/Coerced Variable (Understanding Scope) Rev2k 6 3,433 Jan-09-2020, 03:43 AM
Last Post: Rev2k
  Namespace and scope difference Uchikago 9 4,516 Jul-03-2019, 03:36 PM
Last Post: Uchikago
  what is scope for python? samexpert 2 2,203 Jun-24-2019, 01:03 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020