When is “self” required?

2019-01-15 13:15发布

问题:

I have been using classes for only a short while and when I write a method, I make all variables reference self, e.g. self.foo.

However, I'm looking through the wxPython in Action book and notice that "self" isn't used all the time. For example:

 import wx
 class TextFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, 'Text Entry Example',
            size=(300, 100))
        panel = wx.Panel(self, -1)
        basicLabel = wx.StaticText(panel, -1, "Basic Control:")
        basicText = wx.TextCtrl(panel, -1, "I've entered some text!",
            size=(175, -1))
        basicText.SetInsertionPoint(0)
        pwdLabel = wx.StaticText(panel, -1, "Password:")
        pwdText = wx.TextCtrl(panel, -1, "password", size=(175, -1),
            style=wx.TE_PASSWORD)
        sizer = wx.FlexGridSizer(cols=2, hgap=6, vgap=6)
        sizer.AddMany([basicLabel, basicText, pwdLabel, pwdText])
        panel.SetSizer(sizer)

The one below does use "self".

import wx
class ButtonFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, 'Button Example',
            size=(300, 100))
        panel = wx.Panel(self, -1)
        self.button = wx.Button(panel, -1, "Hello", pos=(50, 20))
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
        self.button.SetDefault()
    def OnClick(self, event):
        self.button.SetLabel("Clicked")

If I remember correctly, "self" is reference to a particular instance of the class, so when is it not necessary? Is there a general rule of thumb?

回答1:

You use self.attribute to reference an attribute of your current instance.

You use wx.Frame.__init__() to reference a method of the parent class.

You don't use self if you only reference a local name (variable) of the method (function) you are in.

These are not "rules of thumb," because there are no exceptions.


What is probably confusing you in this particular example is that panel seems to be only a local name in the constructor, so it looks like the panel would disappear, once your constructor returns.

If you look at the documentation to wx.Panel, though, you will see that its constructor attaches the panel to the parent window, so it will continue to exist, even after the constructor returns.

Magic :)



回答2:

In those instances, if you do not use self then you will create only a local variable of that name. In the first example, panel is created as a local variable and then referenced later in the function, but it won't be available outside that function. The act of passing self to the wx.Panel constructor associated it with the current object in some fashion, so it doesn't just disappear when the function returns.



回答3:

self is always required when referring to the instance itself, except when calling the base class constructor (wx.Frame.__init__). All the other variables that you see in the examples (panel, basicLabel, basicText, ...) are just local variables - not related to the current object at all. These names will be gone when the method returns - everything put into self.foo will survive the end of the method, and be available in the next method (e.g. self.button).