[Tutor] understanding classes [how does 'self' get set?]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Mon, 12 Aug 2002 15:02:21 -0700 (PDT)


On Mon, 12 Aug 2002, Gus Tabares wrote:

> 	I'm reading Learning Python (O'Reilly) and I'm trying to grasp the
> concept of classes. In the book it has the example:
>
> 		class FirstClass:
> 			def setdata(self, value):
> 				self.data = value
> 			def display(self):
> 				print self.data
>
>
> 	Now I kind of understand what's going on here. It's defining a new
> class object called FirstClass. But what I don't understand really is
> the "self" part.
>
> The book says: "Functions inside a class are usually called method
> functions; they're normal defs, but the first argument automatically
> receives an implied instance object when called." I guess I'm just
> looking for a more simplied explanation of 'receives an implied instance
> object'.
>
> I sort of understand that if you set "x = FirstClass()" in this example
> 'self' inside FirstClass "becomes" x. Either that or I just don't know;)


It might help if we make two instances of a FirstClass, because then we'll
have two notions of 'self'.  Let's cause an identity crisis.  *grin*

###
>>> class FirstClass:
...     def setdata(self, value): self.data = value
...     def display(self): print self.data
...
>>> first_instance = FirstClass()
>>> second_instance = FirstClass()
###

Ok, we have two instances of our class now.  At this point, it becomes
ambiguous when we talk about the setdata() method and its parameters
without mentioning the instance.  What do we mean by 'self'?  Do we mean
'first_instance', or 'second_instance'?


Python actually will say something about this ambiguity if we try calling
FirstClass.setdata():

###
>>> FirstClass.setdata(42)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unbound method setdata() must be called with instance as first
argument
###

Notice that Python is complaining that it doesn't know what 'self' is
either!



In order to call a method of a function, we need to tell Python whose
perspective we're using.  If we want to call the setdata() method for our
first_instance, we need to somehow tell Python to use first_instance.

###
>>> first_instance.setdata(42)
>>> second_instance.setdata(81)
>>> first_instance.display()
42
>>> second_instance.display()
81
###

It's the syntax of calling a method of an instance that allows Python to
understand what we mean by 'self'.  What this syntax is trying to
encourage is the thought "'first_instance' is calling it's setdata()
method.  'second_instance' is calling its setdata() method..."

This syntax ties together the instance with its method so that we know
what 'self' will stand for.



By the way, whenever we do something like:

    <instance>.<method name>(<argument 1>, <argument 2>, ...)


Python actually will rotate things around like this:

    <class name>.<method name>(<instance>,
                               <argument 1>, <argument 2>, ...)

But all these fill-in-the-blanks make this too abstract.  Let's look at
our example again.  When we say:

    first_instance.setdata(42)

Python will translate this into a more conventional form:

    FirstClass.setdata(first_instance, 42)

and that's another way of seeing how Python figures things out about self:
we can imagine that Python flips things around so that all the parameters
get filled in properly, including that 'self' parameter.

###
>>> FirstClass.setdata(first_instance, 1.6)
>>> FirstClass.display(first_instance)
1.6
>>> FirstClass.setdata(second_instance, "Go Bears")
>>> second_instance
<__main__.FirstClass instance at 0x811587c>
>>> second_instance.display()
Go Bears
###



Please feel free to ask more questions about this.  Good luck!