question about scope

J

John Salerno

I have the following code:



class DataAccessFrame(wx.Frame):

menu_items = [('File', 'New Database', 'New Record', 'Open
Database...',
'Open Record...', 'Save Record', 'Save All Records',
'Close Record', 'Close Database'),
('Edit', 'Undo', 'Redo', 'Cut', 'Copy', 'Paste'),
('Help',)]

def __init__(self):
wx.Frame.__init__(self, None, title='Database Access Panel')
panel = wx.Panel(self)
self.create_menubar()
# notebook = wx.Notebook(panel)

# sizer = wx.BoxSizer()
# sizer.Add(notebook, 1, wx.EXPAND)
# panel.SetSizer(sizer)

def create_menubar(self):
menubar = wx.MenuBar()
for item in self.menu_items:
menu = wx.Menu()
menubar.Append(menu, item[0])
for subitem in item[1:]:
menu.Append(-1, subitem)
self.SetMenuBar(menubar)

In the create_menubar method, I got an error about the global name
"menu_items" not being defined, and this was fixed by putting "self." in
front of the variable name.

But why is this necessary? Doesn't a method look in its enclosing class,
or is that not one of the levels of scope?
 
S

Steve Holden

John said:
I have the following code:



class DataAccessFrame(wx.Frame):

menu_items = [('File', 'New Database', 'New Record', 'Open
Database...',
'Open Record...', 'Save Record', 'Save All Records',
'Close Record', 'Close Database'),
('Edit', 'Undo', 'Redo', 'Cut', 'Copy', 'Paste'),
('Help',)]

def __init__(self):
wx.Frame.__init__(self, None, title='Database Access Panel')
panel = wx.Panel(self)
self.create_menubar()
# notebook = wx.Notebook(panel)

# sizer = wx.BoxSizer()
# sizer.Add(notebook, 1, wx.EXPAND)
# panel.SetSizer(sizer)

def create_menubar(self):
menubar = wx.MenuBar()
for item in self.menu_items:
menu = wx.Menu()
menubar.Append(menu, item[0])
for subitem in item[1:]:
menu.Append(-1, subitem)
self.SetMenuBar(menubar)

In the create_menubar method, I got an error about the global name
"menu_items" not being defined, and this was fixed by putting "self." in
front of the variable name.

But why is this necessary? Doesn't a method look in its enclosing class,
or is that not one of the levels of scope?

The methods do indeed look in their enclosing class, but only for
self-relative references. These are sought first in the instance, then
in the instance's class, then in the instance's class's superclass, and
so on up to the ultimate superclass. In other words, all attribute
lookup uses the method resolution order ...

You can also reference class variables relative to the class name (i.e.
you could have used DataAccessFrame.menu_items) but that loses a lot of
flexibility.

Also note that when you bind a value to a self-relative name, that
binding *always* occurs in the instance's namespace. Some people don't
like that, but it's a fact of life that others use to provide instance
defaults in class variables that are shadowed by an instance variable
after a first assignment.

regards
Steve
 
J

John Salerno

Steve said:
The methods do indeed look in their enclosing class, but only for
self-relative references. These are sought first in the instance, then
in the instance's class, then in the instance's class's superclass, and
so on up to the ultimate superclass. In other words, all attribute
lookup uses the method resolution order ...

So what I did is correct? It does work, but why don't I have to define
the list as self.menu_items as well?
 
J

James Stroud

John said:
So what I did is correct? It does work, but why don't I have to define
the list as self.menu_items as well?

This is because that list is an attribute of the class. Instances have a
reference of this class attribute, but it can be replaced by an
attribute of the instance with self (self is a reference to the instance
and not the class. This example might help:

py> class C(object):
.... value = 42
.... def separate_from_pack(self, some_value):
.... self.value = some_value
....
py> C.value
42
py> c1 = C()
py> c1.value
42
py> c2 = C()
py> c2.value
42
py> c2.separate_from_pack(88)
py> c2.value
88
py> C.value
42
py> c3 = C()
py> c3.value
42


James

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
 
S

Steve Holden

John said:
Steve Holden wrote:




So what I did is correct? It does work, but why don't I have to define
the list as self.menu_items as well?

The first point is that the name "self" isn't in scope at the point you
make the assignment: it's a local variable (strictly, it's a parameter,
but they are treated the same as locals) to each method, and when the
method is called it's a reference to the specific instance whose method
was called (technically, the instance o which the method is bound).

You could assign self.menu_items in the __init__() method, but it
wouldn't really have any advantages given that names in class scope are
reachable via the name resolution mechanism.

Note that the def statement is also executed in class scope, which is
why the method names are class-relative. Python has a special method
binding feature that changes a call like

instance.method(a1, a2)

into

(instance.__class__).method(instance, a1, a2)

This is where the reference to self "magically" appears from in method
calls.

regards
Steve
 
J

John Salerno

James said:
This is because that list is an attribute of the class. Instances have a
reference of this class attribute, but it can be replaced by an
attribute of the instance with self (self is a reference to the instance
and not the class. This example might help:

Ah, I see! So within my create_menubar() method, would it better to
refer to menu_items as DataAccessFrame.menu_items? Or does it not matter
in this case, since I'm not reassigning it per instance?
 
S

Steve Holden

John said:
James Stroud wrote:




Ah, I see! So within my create_menubar() method, would it better to
refer to menu_items as DataAccessFrame.menu_items? Or does it not matter
in this case, since I'm not reassigning it per instance?

I'd prefer to use a self-relative reference, though either works in your
example. That way the code will work for subclasses with different menus
too. Perhaps not relevant in your case, but a general point.

regards
Steve
 
J

John Salerno

Steve said:
I'd prefer to use a self-relative reference, though either works in your
example. That way the code will work for subclasses with different menus
too. Perhaps not relevant in your case, but a general point.

regards
Steve

Thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top