[Tutor] Function assignment (was: Re: Function type?) [example:new.instancemethod]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Thu Jun 12 13:03:02 2003


On Wed, 11 Jun 2003, Jeff Shannon wrote:

> A few points...
>
> ># Function Description
> >
> >pipe = Item('pipe')
> >def pipe_desc():
> >    if self.parent = player:
> >         return "In your hand."
> >    return "On the floor."
> >pipe.desc = pipe_desc
> >
>
> Actually, this will *not* work.  In your pipe_desc() function, you use
> 'self' -- but there's nowhere for that self to come from!  You need to
> actually have self in the argument list, i.e. 'def pipe_desc(self):
> [...]' However, there's still one more trick needed.  In order for
> 'self' to be given the right value when called as a method, you have to
> tell Python that this is a method of your pipe object.  I believe that
> this can be done using the 'new' module's instancemethod() function.


[warning: the following is very dynamic code; do we really want to do
this?  *grin*]



Here's an example to show how this adding of methods can work:


###
>>> def attachFunction(instance, function, name):
...     """Function to make it a little cleaner to attach
...        a function to an instance."""
...     setattr(instance, name,
...             new.instancemethod(function, instance,
...                                instance.__class__))
...
>>> p1 = Person("Zak")
>>> p2 = Person("Jeff")
>>> def makeGreeter():
...     def f(self):
...         return "Hello, my name is " + self.name
...     return f
...
>>> attachFunction(p1, makeGreeter(), "greet")
>>> attachFunction(p2, makeGreeter(), "greet")
>>> p1.greet()
'Hello, my name is Zak'
>>> p2.greet()
'Hello, my name is Jeff'
###



This is not normally how we'd do the example above; the simpler and more
direct approach might be something like this:

###
>>> class Person:
...     def __init__(self, name):
...         self.name = name
...     def greet(self):
...         return "Hello, my name is " + self.name
...
>>> p1 = Person("Zak")
>>> p2 = Person("Jeff")
>>> p1.greet()
'Hello, my name is Zak'
>>> p2.greet()
'Hello, my name is Jeff'
###


The only reason we're going through that dynamic route is because Zak's
doing it that way.  *grin* But perhaps the simpler approach better mimics
what Inform does?  I'm not too familiar with Inform as a language; let's
take a look at that code snippet again:


!!!

Object pipe
  has   name 'pipe',
        description [;
            if (self in player)
                print_ret "In your hand.";
            else
                print_ret "On the floor.";
        ],
;

! String Description (for comparison)

Object pipe2
  has   name 'pipe',
        description "A boring pipe, with no changing description.",
;

!!!


Here's a few questions I have: in Inform, do the two definitions above
create templates for all kinds of pipes, or do they make single object
instances?  Does Inform allow the addition/attachment of different
attributes to an 'Object' (like 'name' or 'description') after it's been
created?

(Maybe I should look at Inform when I have a chance; looks interesting!)



Without knowing anything, I would have thought the equivalent Python code
would be:

###
## Assume GameObject is defined, and that it has an 'in_player' method

class pipe(GameObject):
    def name(self):
        return 'pipe'
    def description(self):
        if self.in_player():
            return "In your hand."
        else:
            return "On the floor."

class pipe2(GameObject):
    def name(self):
        return 'pipe'
    def description(self):
        return 'A boring pipe, with no changing description."
###



Good luck to you!