[Tutor] when to use "self."

Allan Crooks allan.crooks@btinternet.com
Mon, 02 Jul 2001 17:18:54 +0100


> just another thing i need to get used to i'm guessing :)
> 
> yes, i know about classes. 
> 
> perhaps i'm just confused. when defining a class and giving it some widgets, 
> methods (hum, why not just call them functions?.. grr) and data they all need 
> to be perceded by 'self.' with exception of methods (only a call to one) and 
> variables used internally, non?
> 
> i think i saw an example where this was not the case, hence the confusion.

Ahh, now it makes a lot more sense now. :)

Regarding methods ("why not call them functions"), it's because you are invoking a function which is attached to an object. Some OO king in the past must have come up with the name, and this is his legacy to us. :)

In your initial message, I wasn't entirely sure that whether the full-stop after "self" was intentional or not.

So when do you use "self." ? Whenever you are referring to the attributes of objects.

Let me make a quick class for example's sake. :)

>>> class Thing:
..
..    def __init__(self, val):
..       self.x = val
..
..    def changeX (self, val):
..       self.x = val
..
..    def mutateX (self, val):
..       x = val
..
..    def plaid (self):
..       print "Buy Plaid's Double Figure album right now."
..
..    def plaid_one (self):
..       self.plaid()
..
..    def plaid_two (self):
..       Thing.plaid(self)
..
..    def plaid_three (self):
..       plaid()
..
>>> t = Thing(20)
>>> print t.x
20
>>> t.changeX(30)
>>> print t.x
30
>>> t.mutateX(40)
>>> print t.x
30
>>> t.plaid()
Buy Plaid's Double Figure album right now.
>>> t.plaid_one()
Buy Plaid's Double Figure album right now.
>>> t.plaid_two()
Buy Plaid's Double Figure album right now.
>>> t.plaid_three()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 22, in plaid_three
NameError: global name 'plaid' is not defined
>>>

And before you ask, no, I'm not in any way involved with Plaid, I'm only a fan who wants to spread the word. :)

So let's take the first part of the class.

..    def __init__(self, val):
..       self.x = val
..
..    def changeX (self, val):
..       self.x = val
..
..    def mutateX (self, val):
..       x = val

>>> t = Thing(20)
>>> print t.x
20
>>> t.changeX(30)
>>> print t.x
30
>>> t.mutateX(40)
>>> print t.x
30

Now when we create a thing object, we assign the value provided in the call to the actual instance (self) of a Thing object.

Now when we run changeX, we have to qualify the x as "self.x". When we run mutateX, it doesn't change the value in self, because "x" is a variable in the namespace of the method itself. But we want to modify the value in the namespace of the newly created Thing object, so we HAVE to qualify the x with self.

This is a little confusing to people who have programmed in Java initially (e.g me :)). The equivalent Java code is:

public void changeX (int value) {
  this.x = value;
}

And this is the same too:

public void changeX (int value) {
  x = value;
}

But that's because namespaces work differently to Python's. So in other words, you NEED to put "self." before you refer to a variable that's attached to an object.

Now the part regarding methods:

..    def plaid (self):
..       print "Buy Plaid's Double Figure album right now."
..
..    def plaid_one (self):
..       self.plaid()
..
..    def plaid_two (self):
..       Thing.plaid(self)
..
..    def plaid_three (self):
..       plaid()
..

>>> t.plaid()
Buy Plaid's Double Figure album right now.
>>> t.plaid_one()
Buy Plaid's Double Figure album right now.
>>> t.plaid_two()
Buy Plaid's Double Figure album right now.
>>> t.plaid_three()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 22, in plaid_three
NameError: global name 'plaid' is not defined
>>>

Now the first method ("plaid") is a shameless plug.

The second method ("plaid_one") calls the first one using self. So it will invoke the method attached to the object instance (so if we override the definition of "plaid", it will do something else).

The third method ("plaid_two") is invoking the definition of "plaid" that is defined in the Thing class. So even if we supply an instance of Thing which is it is overridden, it will still advertise the album. :)

So we come to the fourth method ("plaid_three"). We attempt to invoke it, but it doesn't work, since "plaid" doesn't exist in the local, global or builtin namespaces.

So, plaid_one searches in the object's ("self") name space. plaid_two searches in the namespace of "Thing". plaid_three searches in the local ("plaid_three") name space, global namespace and then the builtin namespace, and then fails.

So that should make things clearer. Apologies if parts of this message doesn't make sense, I've got too many distractions. :)

So whatever you read about not using "self." is a complete lie. :)

Allan.