new.instancemethod

James_Althoff at i2.com James_Althoff at i2.com
Thu May 17 16:06:14 EDT 2001


"Alex Martelli" <aleaxit at yahoo.com> wrote:
><James_Althoff at i2.com> wrote in message
>news:mailman.990039435.21839.python-list at python.org...
>    ...
>> True.  On the other hand, Python does support instance-specific methods.
>
>You mean bound-methods, right?

Actually, I was thinking of the general concept whereby the implementation
of a method for a given instance differs from the implementation of that
method as defined in the class of that instance.  "Python supports this"
was meant in the sense that for an instance "x" and attribute "m" (meant to
be a method in this example) Python looks *first* in the dict of "x" for
"m" when encountering "x.m" (because that's how it handles any attribute
lookup) as contrasted with other OO languages that go directly to the class
of "x" to find method "m".

An illustration of this might be:

class Class1:

    def show(self):  # behavior for Class1 instances
        print 'Class1.show:', self

class Class2(Class1):

    def show(self):  # change behavior for Class2 instances
        Class1.show(self)
        print 'Class2.show:', self

c1 = Class1()  # normal c1 instance
c2 = Class2()  # normal c2 instance
c2x = Class2() # special c2 instance

def c2x_show(self):  # change behavior for the c2x instance only
    self.__class__.show(self)  # invoke the method as defined in my class
    print 'c2x.show:', self    # do something special for cx2
import new
c2x.show = new.instancemethod(c2x_show,c2x,Class2)

print
c1.show()
print
c2.show()
print
c2x.show()
print

>>> reload(test3)

Class1.show: <test3.Class1 instance at 00816BAC>

Class1.show: <test3.Class2 instance at 0081156C>
Class2.show: <test3.Class2 instance at 0081156C>

Class1.show: <test3.Class2 instance at 00816ACC>
Class2.show: <test3.Class2 instance at 00816ACC>
c2x.show: <test3.Class2 instance at 00816ACC>

<module 'test3' from 'c:\_dev\python20\test3.pyc'>
>>>

>
>> So what is a nice example usage of this capability and what is a good
>> practice for its implementation?
>
>What capability, exactly?  Bound methods, unbound ones, the new
>module...?

>From time to time I read discussions about the importance of
"instance-specific behavior".  Often the example given is along the lines
of wanting different GUI button instances to act differently when clicked.
Although this situation comes up all the time, I find that I usually handle
it with something like:

class Button:

    def __init__(self,name):
        self.name = name
        self.onClick = None

    def setOnClickHandler(self,handlerMethod):
        self.onClick = handlerMethod


class GUIViewController:

    def __init__(self):
        self.button1 = Button('button1')
        self.button2 = Button('button2')
        self.button1.setOnClickHandler(self.handleButton1)
        self.button2.setOnClickHandler(self.handleButton2)

    def handleButton1(self):
        print 'do something useful for button1'

    def handleButton2(self):
        print 'do something useful for button2'

    def pretendToRun(self):
        self.button1.onClick()
        self.button2.onClick()

GUIViewController().pretendToRun()

>>> reload(test2)
do something useful for button1
do something useful for button2
<module 'test2' from 'c:\_dev\python20\test2.py'>
>>>

as opposed to:

class Button:

    def __init__(self,name):
        self.name = name

    def onClickDo(self): pass


class GUIViewController:

    def __init__(self):
        self.button1 = Button('button1')
        self.button2 = Button('button2')
        def button1_onClickDo(self):
            print 'do something useful for button1'
        def button2_onClickDo(self):
            print 'do something useful for button2'
        import new
        self.button1.onClickDo = new.instancemethod(
            button1_onClickDo,self.button1,Button)
        self.button2.onClickDo = new.instancemethod(
            button2_onClickDo,self.button2,Button)

    def pretendToRun(self):
        self.button1.onClickDo()
        self.button2.onClickDo()

GUIViewController().pretendToRun()

>>> reload(test1)
do something useful for button1
do something useful for button2
<module 'test1' from 'c:\_dev\python20\test1.pyc'>
>>>

It seems that often when you want "instance-specific behavior" that
behavior is determined by the context where you create and/or use the
instance so that the first approach above (passing around and saving a
method/function from the "context" object that created the instance) is
more useful than the second (doing an "instance-based override" of a method
that is defined in the instance's class -- I realize that method/function
objects are still being passed around and saved even in this second
example.  The main difference that I am looking at is the value of the
"im_self" attribute of the method object).

IOW, for most of the examples I see where "instance-specific behavior" is
useful a reasonable strategy is for the instance to delegate immediately
back to the object/context that created (or uses) it to do something
meaningful on its behalf.

Given that, I was wondering if anyone had a good example from actual
practice where the "instance-override-of-method"-type approach was the best
way to go.  And if there is such an example, is using the module "new" the
best way or is there another approach (such as the one Alex showed in the
previous post) that avoids using the "new" module.

<snip>

>I'm having something of a hard time understanding exactly what you
>are asking, but I'll give it a try.

Thanks for your input, Alex.  I see how your suggestions works: add a
function to the class of the instance, use the "dot" mechanism to retrieve
a bound method on the instance from the class, assign it to the single
instance, then delete it from the class object.  That's neat.

<snip>

>Not that comes to mind.  I have never had the need to store a
>bound method as an attribute of the object to which it was
>bound -- it seems more common, if stored it needs to be, to
>store it elsewhere.

That's what I suspect, also.

>Nor have I ever actually needed this
>new-eschewing black magic, nor can I think why one would
>prefer that to module new.

Ditto for me.

>
>
>Alex

Jim





More information about the Python-list mailing list