[Tutor] Function output

Daniel Yoo dyoo@hkn.EECS.Berkeley.EDU
Wed, 28 Jun 2000 02:16:29 -0700 (PDT)


Hello!

On Mon, 26 Jun 2000, William Perry wrote:

> embarrested to admit that the terminology I used in the original
> question was incorrect. What I'm actually trying to do is get method
> output from a class. ( Thanks to the first set of answers I have the

Don't feel embarrased --- this is how we learn!  Ok, let's take a look at
your code:


> >>> class rollum:
>  def funct1 (self):
>   s = " Hello World"
>   return s
>  def output (self):
>   a = funct1()
>   return a
> 
> >>> rollum.output()
> Traceback (innermost last):
>   File "<pyshell#42>", line 1, in ?
>     rollum.output()
> TypeError: unbound method must be called with class instance 1st argument

I see, so you want to be able to call the functions inside the class,
but without saying something like:

  r = rollum()
  r.funct1()

I'll assume that you've read through a bit of Chapter 6 in Learning
Python, which talks about this.  In fact, from my copy, it looks like Pg.
160 talks about this topic --- you can look at it afterwards to see if it
makes more sense.

The member functions of a class need to be "bound" to some instance of
that class.  From the interpreter, rollum.funct1 is:

###
>>> rollum.funct1
<unbound method rollum.funct1>
###


Let's say we have a rollum instance called r.  Here's a way to call
rollum.funct1:

###
>>> r = rollum()
>>> rollum.funct1(r)
'Hello World!'
###

What Python does normally when we say "r.funct1()" is to bind 'r' to the
first argument of function funct1.  That's what 'self' is.  When you
manually pull out that function via "rollum.funct1", you need to also
manually insert 'self' into the function to make it work again.


If we look at a simpler example, this'll make more sense:

###
class SayHello:
  def speak(self):
    print "Hello!"

s = SayHello()
###

then "SayHello.speak(s)" and "s.speak()" do the same thing:

###
>>> SayHello.speak(s)
Hello!
>>> s.speak()
Hello!
###


Normally, you usually do the latter, since it's shorter to write.  It is
very good that you're looking at this, however, because later in Chapter
6, you'll get introducted to the idea of inheritence, where this sort of
stuff becomes very useful.


I'll introduce a bit of it here.  In inheritence, you can take a
preexisting class, and augment it slightly with different behavior.  
Let's say we're simulating a courteous child who's learning how to count.

###
class Beginner:
  def sayHello(self):
    print "Hello there."
  def count(self):
    print "I can count to one!"
###

Ok, simple enough.  But let's say we want to make an intermediate, who's
studied tons and tons, who can count to an extraordinarily high number,
and yet is still able to greet us warmly.  We'd like to see something
like:

  "Hello there."
  "I can count to one!"
  "I can count to two!"

We could write this as follows:

###
class Intermediate(Beginner):
  def count(self):
    print "I can count to one!"
    print "I can count to two!"
###

and we'd be able to do something like:

###
child = Intermediate()
child.sayHello()
child.count()
###

That extra syntax in the class definition of Intermediate means: "Let's
borrow all of the definitions of the Beginner, all except the count
function, because that's being redefined".  This allows us to let an
Intermediate sayHello() still, even though we haven't explicitly written
it.

You might notice, however, that instead of completely replacing the
definition of the beginner's count(), we might want to build on top of
that.  Learning is by building on top of what you already know.  How can
we do that?  This will look familiar to you:

###
class Intermediate(Beginner):
  def count(self):
    Beginner.count(self)
    print "I can count to two!"
###


Here's the interpreter session:

###
>>> child = Intermediate()
>>> child.count()
I can count to one!
I can count to two!
###


Again, if you have any questions, feel free to ask!